Introduction
This workshop offers an introduction to time series cross sectional
(TSCS) data with a focus on applications in R. Some familiarity with
time series cross sectional econometrics, as well as R, is assumed. We
will cover some basic theoretical results, but this workshop is not
intended to substitute for a more detailed theoretical treatment.
The workshop starts with some basic description of the structure of
TSCS data and the risks of the pooled (OLS) estimator, then covers
standard approaches to unit-level heterogeneity: the fixed effect
(within) estimator, the random effect estimator. Interpretation and
drawbacks of the fixed effect estimator are discussed, as well as a
potential solution to the time invariant covariate problem via penalized
maximum likelihood. We will discuss testing the key assumption behind
the random effects model, and introduce the unifying “within-between”
model.
The second section focuses on issues related to time. We start by
considering the implications of a static model, then incorporate basic
dynamics via the finite distributed lag and lagged dependent variable
(LDV) specification. We briefly discuss tests for serial correlation in
the model errors, as well as introduce the Anderson-Hsiao estimator for
FE estimation with an LDV.
Setup
Packages
install.packages() and library() for package
downloads and loading. Here we’ll load some useful packages [c converts
elements into a vector]
#install.packages(c("tidyverse", "data.table", "readstata13", "plm", "bife", "survival", "brglm2", "ivreg", "lmtest", "tseries", "plotly"))
library("tidyverse")
library("tseries")
library("data.table")
library("readstata13")
library("plm")
library("bife")
library("survival")
library("brglm2")
library("ivreg")
library("lmtest")
library("plotly")
#setwd()
set.seed(1015)
Review of OLS and the Linear Model
Some clarification of terminology
A linear regression models a dependent variable \(Y\) as a function of one or more
independent variables (\(X\)) and an
error term \(\epsilon\)
(Ordinary) Least Squares (OLS/LS) is a popular estimator of the
linear model, but not the only estimator
Ridge Regression / Lasso are examples of other estimators of the
linear model
From an ML perspective, linear regression is a form of supervised
learning while OLS is uses error minimization as measured by the sum of
squared residuals
Intuition
Create a univariate linear relationship using a Monte Carlo
simulation
sample <- 200
x <- rnorm(sample, 0, 2)
e <- rnorm(sample, 0 , 10)
y <- 3 + x + e
univariate <- data.frame(y, x)
univariate
plot<-univariate %>%
ggplot(aes(x, y)) +
geom_point()
ggplotly(plot)
Estimating a univariate linear model is equivalent to drawing a
straight line through this scatter plot
Can fit any number of linear models to this data - need a criteria
for determining the best model
OLS posits that the best model is one that minimizes the error of the
model’s predicted \(Y\) and the real
\(Y\)
OLS measures model error as the sum of squared resiudals
univariate$pred <- predict(lm(y~x, data=univariate))
univariate$resid <- univariate$y - univariate$pred
resid_plot<-univariate %>%
ggplot(aes(x, y)) +
geom_point()+
geom_smooth(method = "lm", se=F)+
geom_segment(aes(xend=x, yend = pred), color="red")
ggplotly(resid_plot)
`geom_smooth()` using formula = 'y
~ x'
Coefficient Variance
OLS is unbaised, but any individual estimate of \(\hat\beta\) may be far from \(\beta\)
The variance of \(\hat\beta_1\) is a
function of the variance of the error and the variance of \(X\)
Higher variance in the error makes estimation less precise while
higher variance in \(X\) makes it more
precise:
\[ Var(\hat\beta_1) =
\frac{\sigma^2}{\sum_{i=1}^n(x_i-\overline{x})^2} \] Denominator
is known as a function of the data - numerator is unknown and must be
estimated
An unbiased estimator of \(\sigma^2\) is \(RSS/(n-2)\) where \(n-2\) is a degrees of freedom adjustment
due to constraints of OLS
For test statistics, we work with the standard error of the
coefficient, as opposed to the variance
\[se(\hat\beta_1) =
\sqrt\frac{\sigma^2}{\sum_{i=1}^n(x_i-\overline{x})^2} =
\sqrt\frac{RSS/(n-2)}{\sum_{i=1}^n(x_i-\overline{x})^2} \]
Multiple Regression
Consider a linear model where \(Y\)
is a function of two independent variables:
\[Y = \beta_0 + \beta_1 X_1 + \beta_2 X_2
+ \epsilon\]
x1 <- rnorm(sample, 0, 5)
x2 <- 2*x1 + rnorm(sample, 0, 5)
y <- 2*x1-x2+rnorm(sample, 0,5)
multivariate <- data.frame(x1, x2, y)
multi_plot<-plot_ly(multivariate, x = ~x1, y = ~x2, z = ~y)
multi_plot<-multi_plot %>%
add_markers()
multi_plot
Estimation of this linear model via OLS is similar
Recall OLS minimizes \(RSS\)
\[ RSS = \sum_{i=1}^{n}e_i^2\]
\[ = \sum_{i=1}^{n}(\hat{y_i} - y_i)^2
\] \[ = \sum_{i=1}^{n}((\hat{\beta_0}
+ \hat{\beta_1}X_{1i} + \hat{\beta_2}X_{2i}) - y_i)^2 \] When we
model \(Y\) as a function of \(X_2\) OLS minimizes \(RSS\) over both \(X\)
The formula for coefficients of multivariate regression are more
complicated, but one representation:
\[\hat\beta_1 =
\frac{\sum_{i=1}^{n}\hat{r_{i1}}y_i}{\sum_{i=1}^{n}(\hat{r_{i1}})^2}
\] Where \(\hat{r_{i1}}\) is the
residual from the auxiliary regression of \(X1\) on \(X2\)
\[ X_1 = \hat\gamma_0+\hat\gamma_1{X_2} +
\hat{r_1} \] Note that our new estimate for \(\hat\beta_1\) is identical to our old
estimate except that \(Cov(\hat{r},
y)\) and \(Var(\hat{r})\) have
replaced \(Cov{x, y}\) and \(Var(x)\) respectively
The specific form of these variances and covariances is slightly
different - note no means! We’ve applied two simplifications to drop
means
\[ E[\hat{r}] = 0 \]
\[ Cov(x, y) = \sum_{i=1}^{n}(x_i -
\overline{x})(y_i - \overline{y}) = \sum_{i=1}^{n}(x_i -
\overline{x})y_i \]
Illustration of Multiple Regression by Partial Regression
multivariate$resid <- residuals(lm(x1~x2, multivariate))
partial <- lm(y~resid, multivariate)
full <- lm(y~x1+x2, multivariate)
print(c(coef(partial), coef(full)))
Illustration of Omitted Variable Bias
short <- lm(y~x1, multivariate)
print(coef(short))
aux <- lm(x2~x1, multivariate)
coef(full)[2] + coef(full)[3]*coef(aux)[2]
Frequentist Statistical Inference
Fundamental question: does \(X\)
effect \(Y\)?
Frequentist inference begins by assuming the opposite. We refer to
this as the null hypothesis:
\(H_0\): There is no relationship
between \(X\) and \(Y\)
Under the null hypothesis - what do we expect \(\hat\beta_1\) to be?
Statistically, we want to test how likely our estimate of \(\hat\beta_1\) under the null hypothesis -
in other words if the effect of \(X\)
is zero, how unlikely is our estimate?
This depends on the coefficient and it’s variance, which we use to
construct a t-statistic:
\[t = \frac{\hat\beta_1 -
\beta_{1|H_0}}{se(\hat\beta_1)} \]
Under the normality assumption:
\[ \epsilon \sim Normal(0, \sigma^2)
\]
The t-statistic follows a t-distribution with n-k-1 degrees of
freedom. Knowing this we can calculate a p-value which
represents the probability that we could draw a test statistic at least
as large as \(T\) (one tailed test) or
at least as large as \(|T|\) (two
tailed)
Note that normality implies homoskedasticity
Manual Illustration
univariate$y_hat = beta0_hat + beta1_hat * univariate$x
rss = sum((univariate$y_hat - univariate$y)^2)
se_beta1 <- sqrt(
(rss/(sample-2))/
sum((univariate$x - mean_x)^2)
)
t <- beta1_hat/se_beta1
p <- 2*pt(abs(t), df=sample-2, lower=F)
print(c(t, p))
LM Function
lm <- lm(y~x, data=univariate)
summary(lm)
plot(lm)
TSCS Data
TSCS data have observations of multiple units N over time
T.
Each specific observation within the data is of one unit at one time,
e.g.
data<-read.dta13("ms_mil_spend_data.dta")
data %>%
filter(ccode==2, year==2000)
This observation is for the US (2) for the year 2000.
data %>%
dplyr::arrange(ccode, year) %>%
dplyr::select(ccode, year, LMILEX, v2x_polyarchy)
data %>%
dplyr::filter(ccode %in% c(2,20)) %>%
ggplot(aes(x=year, y=LMILEX)) +
geom_line() +
facet_wrap(~ccode)
Within / Between Decomposition
summary(data$LMILEX)
#Between unit variation
data %>%
group_by(ccode) %>%
summarize(between=mean(na.omit(LMILEX)))%>%
dplyr::select(between) %>%
ungroup() %>%
summary()
#Within unit variation
data %>%
group_by(ccode) %>%
mutate(between=mean(na.omit(LMILEX)),
within=LMILEX-mean(na.omit(LMILEX))) %>%
dplyr::select(within) %>%
ungroup() %>%
summary()
Pooling
The simplest approach to estimating a model on TSCS is to pool the
data:
\(Y_{it}=\beta_0+\beta_1X_{it}+e_{it}\)
Where Y is the DV, X is the IV, \(\beta_0\) is the intercept, \(\beta_1\) is the coefficient on X and \(e_{it}\) is the error.
What are we assuming here?
All of the \(N\) units share a
common intercept \(\beta_0\) and a
common slope \(\beta_1\) on X.
Standard OLS assumptions regarding the error term (specifically zero
conditional mean and white noise errors).
Whether pooling is appropriate depends on whether those assumptions
are correct.
Clean Pool
#Monte Carlo simulations to better control the relationships
N<-seq(1,5,1)
Time<-seq(1,50,1)
clean<-expand.grid(N, Time)
names(clean)<-c("N", "Time")
clean<- clean %>%
dplyr::arrange(N, Time)
tibble(clean)
#Draw the IV, DV, error
clean$X<-rnorm(nrow(clean), 1, .25)
clean$Y<-3-2*clean$X+rnorm(nrow(clean), 0, .5)
tibble(clean)
#Run the pooled model
clean_pool<-lm(Y~X, data=clean)
summary(clean_pool)
#Plot to understand why this worked
clean %>%
ggplot(aes(x=X, y=Y))+
geom_point(aes(color=as.factor(N)))+
geom_smooth(method="lm", se=F)
Pooled model works here because there is no difference in the
underlying relationship - we know this because we drew X without respect
to N, Time
Dirty Pool
Let’s assume instead that there exists some unit-level heterogeneity.
Some \(Z\) affects both \(Y\) and \(X\) but is time constant.
You may recognize this as the setup for omitted variable bias.
#Monte Carlo simulations to better control the relationships
N<-seq(1,5,1)
Time<-seq(1,50,1)
dirty<-expand.grid(N, Time)
names(dirty)<-c("N", "Time")
dirty<- dirty %>%
dplyr::arrange(Time, N)
#Draw the unobserved effect, IV, DV, error
Z<-rnorm(length(unique(dirty$N)), 0, .5)
dirty$Z<-rep(Z, length(Time))
dirty$X<-dirty$Z+rnorm(nrow(dirty), 1, .25)
dirty$Y<-3-2*dirty$X+4*dirty$Z+rnorm(nrow(dirty),0, .5)
#Run the pooled model
dirty_pool<-lm(Y~X, data=dirty)
summary(dirty_pool)
#Plot the pooled model - what are we looking at?
dirty %>%
ggplot(aes(x=X, y=Y))+
geom_point()+
geom_smooth(method="lm", se=F)
dirty %>%
ggplot(aes(x=X, y=Y))+
geom_point(aes(color=as.factor(N)))+
geom_smooth(method="lm", se=F)
#Plot the per unit regressions
dirty %>%
ggplot(aes(x=X, y=Y, color=as.factor(N)))+
geom_point()+
geom_smooth(method="lm", se=F)
In this case, pooling estimates a weak positive relationship between
X and Y, despite the fact that the true relationship is negative.
This occurs because there is omitted variable bias introduced by
Z.
Note that pooling would be fine if we could estimate \(Y_{it}=\beta_1X_{it}+\beta_2Z_i+e_{it}\)
Fixed Effects
With TSCS data that contains time-constant unit-level omitted
variable bias, fixed effects can be used to estimate the unbiased
relationship, even if the omitted variable \(Z\) is not observed.
fe<-plm(Y~X, dirty, index=c("N", "Time"), method="within")
summary(fe)
Why does this work?
The fixed effect estimator considers only the within-unit variation,
and removes the between unit variation.
In other words, the data are group demeaned- each observation for
each i is subtracted from the mean for that unit over time.
Because the effect of Z is constant over time, demeaning
removes its effect and the bias it introduces
We can do this manually:
demean<-dirty %>%
dplyr::arrange(N,Time)%>%
dplyr::group_by(N) %>%
dplyr::mutate(mean_X=mean(X),
mean_Y=mean(Y),
demean_X=X-mean_X,
demean_Y=Y-mean_Y)
demean
fe_manual<-lm(demean_Y~demean_X-1, data=demean)
summary(fe_manual)
demean %>%
ggplot(aes(x=demean_X, y=demean_Y))+
geom_point(aes(color=as.factor(N)))+
geom_smooth(method="lm", se=F)
The within estimator is typically introduced with the dummy variable
notation - where N indicators for each unit (or N-1 and the intercept).
These are equivalent in OLS (not in GLMs). Most software (plm in R,
xtreg, fe in Stata) uses the within transform
fe_dummy <-
lm(Y~X+as.factor(N)-1, data=dirty)
summary(fe_dummy)
summary(fe_manual)
summary(fe)
Note that the standard errors are slightly different because the
demeaned model doesn’t have the right degrees of freedom. You should use
plm() for the within transform as it corrects for this.
Interpretation
Interpretation is standard, but with a caveat
summary(fe)
sd(dirty$X)
coef(fe)*sd(dirty$X)
sd(demean$demean_X)
coef(fe)*sd(demean$demean_X)
Takeaway: Coefficients on Linear FE regressors are correctly
interpreted as the effect of a one unit increase in the within
unit X. The within unit variance is always no larger than the total
variance in X (often significantly smaller, here about 1/2). Calculate
substantive effects using within X. (Mummolo and
Peterson (2018))
Drawbacks
- No estimates for time-invariant variables
time_inv<-dirty
time_inv$K<-ifelse(dirty$N<=2, 1, 0)
time_inv$Y<-3-2*time_inv$X+4*time_inv$Z-3*time_inv$K+rnorm(nrow(time_inv),0, .5)
drop_model<-plm(Y~X+K, model="within", index = c("N", "Time"), data=time_inv)
summary(drop_model)
#Why not?
time_inv %>%
group_by(N) %>%
mutate(var_k=K-mean(K)) %>%
ungroup() %>%
select(var_k) %>%
summary()
The FE estimator sweeps out all variation on K, because K only has
between-unit variance, not within unit variance.
- Loss of observations without variation in the DV in either
conditional or unconditional logistic regression.
data %>%
group_by(ccode) %>%
summarize(var_dem=var(na.omit(vdem_dem)))
logit<-clogit(vdem_dem~LMILEX+strata(ccode), data=data)
summary(logit)
A lot has been made of this issue, but does it matter? (Cook, Hays, and Franzese (2020))
“Feels” problematic that the model ignores a portion of the data. Can
be severe if the event in question is rare/common.
Concrete issues:
No estimates of FE, so no individual MEs (similar to Cox PH
model).
Biased estimates of baseline rate of event because non-event
units are removed. Correct interpretation is baseline rate for units
that experience the event.
Penalized ML
Cook, Hays, and Franzese (2020) recast the unconditional
(unit-dummy) FE problem as one of separation.
Separation occurs when a variable perfectly predicts the DV- here the
unit does. (Imagine a table of Y and N, if one or more cells are empty,
this is separation)
ML solutions do not exist under separation- the LL is flat
because fit can always be improved by pushing the separating coefficient
more towards negative (positive) infinity.
Well known solution is to penalize the maximum likelihood to punish
large coefficients (may be familiar as ridge/lasso, but specific penalty
is different.)
penalized_fe<-glm(vdem_dem~LMILEX+as.factor(ccode), data=data,
familty="binomial"(link="logit"), method="brglmFit")
summary(penalized_fe)
Note that the unconditional FE estimator is biased due to the
incidental parameters problem, which can be severe in small T.
Penalizing the ML does not change this.
Incidental parameters problem is just a special case of well known
small sample bias of MLE (MLE is consistent, not unbiased, and
consistency relies on asymptotics).
As N grows without T, the number of ‘incidental parameters’ (the unit
dummies) grows, so we are using T periods to estimate a greater and
greater number of parameters.
Random Effects
What if \(Z\) does not cause \(X\)?
There’s no OVB (recall necessary conditions)
FE estimator is still unbiased
Pooled estimator unbiased, but incorrect SE/t-stats because unit
effect creates serial correlation in errors
#Make some data to better control the relationships
N<-seq(1,5,1)
Time<-seq(1,50,1)
random<-expand.grid(N, Time)
names(random)<-c("N", "Time")
random<- random %>%
dplyr::arrange(Time, N)
#Draw the unobserved effect, IV, DV, error
Z<-rnorm(length(unique(random$N)), -2, .5)
random$Z<-rep(Z, length(Time))
random$X<-rnorm(nrow(random), 1, .25)
random$Y<-3-2*random$X+4*random$Z+rnorm(nrow(random),0, .5)
#Run the pooled model
random_pool<-lm(Y~X, data=random)
summary(random_pool)
#Plot the pooled model - what are we looking at?
random %>%
ggplot(aes(x=X, y=Y))+
geom_point(aes(color=as.factor(N)))+
geom_smooth(method="lm", se=F)
#Plot unit intercepts/slopes
random %>%
ggplot(aes(x=X, y=Y, color=as.factor(N)))+
geom_point()+
geom_smooth(method="lm", se=F)
#RE estimator
re<-plm(Y~X, random, model = "random")
summary(re)
Pooled model has incorrect variance
#True error
random$error <-random$Y-(3-2*random$X+4*random$Z)
#Get estimated error from pooled model
random$resid<-resid(random_pool)
random %>%
dplyr::select(error, resid) %>%
pivot_longer(cols = everything()) %>%
ggplot()+
geom_histogram(aes(value, fill=name, alpha=.2))+
guides(alpha="none")
e_resid = sum((random$resid)^2)/248
e_error = sum((random$error)^2)/250
e_resid
e_error
# How does this affect beta se and t-stats?
sqrt(e_resid / sum((random$X - mean(random$X))^2))
sqrt(e_error / sum((random$X - mean(random$X))^2))
summary(random_pool)
summary(re)
We can see that our SEs (and by extension t-stats) for the pooled
model are incorrect. This is becuase our estimate of \(\sigma^2\) (variance of the error term) is
wrong because the pooled estimator includes the effect of \(Z\) on \(Y\) in the variance.
Random effects purge the variance contributed by \(Z\) and therefore return SE that match SE
calculated with the known error term.
Autocorrelation robust standard errors
Since the pooled model is unbiased, we can simply correct the
standard error esitmates. Here using cluster-robust SE.
However, cluster-robust SE are asymptotically correct (in
the number of units \(N\) not
the number of observations). Our N is 5, which is…not
asymptotic.
coeftest(random_pool, vcov=vcovHC(random_pool, type = "HC0", group="N"))
These look very similar to our uncorrected SEs.
Make the data bigger.
#Make some data to better control the relationships
N_large<-seq(1,5000,1)
Time<-seq(1,50,1)
random_large<-expand.grid(N_large, Time)
names(random_large)<-c("N", "Time")
random_large<- random_large %>%
dplyr::arrange(Time, N)
#Draw the unobserved effect, IV, DV, error
Z_large<-rnorm(length(unique(random_large$N)), -2, .5)
random_large$Z<-rep(Z_large, length(Time))
random_large$X<-rnorm(nrow(random_large), 1, .25)
random_large$Y<-3-2*random_large$X+4*random_large$Z+rnorm(nrow(random_large),0, .5)
#Run the pooled model
random_pool_large<-lm(Y~X, data=random_large)
summary(random_pool_large, cluster="N")
large_e_error <- sum((random_large$Y -(2*random_large$X+4*random_large$Z))^2)/(length(N_large))
sqrt(large_e_error / sum((random_large$X - mean(random_large$X))^2))
Testing the validity of the RE assumption
In order to be unbiased, the Random Effects estimator requires that
there is no correlation between the unit effects and the explanatory
variables.
This assumption is typically tested with a Hausman test comparing an
FE and RE model with the same specification
#Fit a FE model to the same data
fe<-plm(Y~X, random, model = "within")
#Hausman Test
phtest(fe, re)
#Note, order of the arguments does not matter
#Can also calculate the Hausman statistic by hand
t(coef(fe) - coef(re)[2])%*% solve(vcov(fe)-vcov(re)[2,2]) %*% (coef(fe)-coef(re)[2])
The null hypothesis of the Hausman test is (roughly) that the
coefficient vectors are equal in both the FE and RE models. Rejection
indicates the two vectors are statistically different. Rejection is
typically taken to suggest violation of the RE assumption.
Recall that both the FE and RE models are unbiased under the RE
assumptions (the former is not efficient). Thus, if the RE assumptions
hold, we would not expect a difference. In contrast, if the RE
assumption regarding the correlation of the individual effects with the
independent variables is violated, only the FE estimator is unbiased and
the RE estimator is biased. Therefore, we would expect differences in
the estimates.
The Within-Between Model
Rather than choosing between fixed and random effects, we can
estimate a compound model.
Recall that the goal of both the FE and RE models is to account for
unit-level heterogeneity. The fundamental difference is that the RE
model requires no covariance between the unit effects and the error. The
FE model is agnostic on this because it eliminates all variation on all
variables due to unit effects via the within transform (subtracting the
unit means from each realization of \(Y\), \(X\))
The risk of the RE model, then, can be thought of as correlation
between these unit means and the error term. As with standard OVB,
putting the unit means into the equation will remove the bias and allow
the RE estimator to recover the unbiased coefficients on \(X\).
The traditional approach comes from Mundlak
(1978) and involves
estimating the following equation with the RE estimator:
\(Y_{it}=\beta_1X_{it}+\beta_2\overline{X_i}+e_{it}\)
Where \(\overline{X_i}\) is the unit
level mean of \(X\)
Alternatively, the time-specific realizations of \(X\) can be within-transformed prior to
estimation.
\(Y_{it}=\beta_1(X_{it}-\overline{X_i})+\beta_2\overline{X_i}+e_{it}\)
The specific model you should use depends on which coefficients are
more of interest: the individual or aggregate. The former (Mundlak)
specification facilitates interpretation of the aggregate (group mean)
variable.
The group demeaning in the latter approach ensures that the
individual realizations are uncorrelated with the group-level mean. As a
result, the group-level term cannot be interpreted, because it does not
control for the effect of the individual realizations.
#We'll fit the second equation to our RE data
#First, we have to group demean
demean_random<-random %>%
dplyr::arrange(N,Time)%>%
group_by(N) %>%
mutate(mean_X=mean(X),
demean_X=X-mean_X)
# Now include both X terms in the RE model
rebw<-plm(Y~demean_X + mean_X, demean_random, model = "random")
coef(rebw)
coef(fe)
Notice that the coefficient on the within effect from the REBW model
is the same as the FE estimate.
We can also estimate the Mundlak version
#Mundlak formulation
mundlak<-plm(Y~X + mean_X, demean_random, model = "random")
coef(mundlak)
Again, we’ve successfully purged the coefficients on the individual
realizations of \(X\). Our coefficient
on \(\overline{X}\) has changed. The
REWB estimate was -56 which we can see here is actually the sum of the
between and within coefficients from the Mundlak estimator of -54 and
-2
Dynamic Models
#Check how our data look
data %>%
dplyr::select(c(ccode, year, LMILEX, v2x_polyarchy)) %>%
filter(ccode<100) %>%
pivot_longer(cols = c(LMILEX, v2x_polyarchy), values_to = "values")%>%
ggplot(aes(y=values, x=year, color=as.factor(ccode)))+
geom_line()+
facet_wrap(~name, scales="free_y")
Panel Unit Root Testing
Panel unit root testing is difficult and R implementations are
somewhat basic
We can perform our own test via the p-value aggregation method of
Choi (2001)
We perform an augmented Dickey-Fuller test on each panel, aggregate
the p-values
Specific aggregation is \(-2\sum_{n}^{N}
ln(p_n)\)
Test statistic is distributed \(\chi^2(2N)\)
N here indicates number of panels
We’re going to loop over the panels, perform the test, store the
results
(You could also do this as a vectorized function…)
pvals <- NULL
for (i in unique(data$ccode)){
try(dfuller <- adf.test(data[data$ccode==i, "LMILEX"], k = 1))
pvals<-rbind(pvals, dfuller$p.value)
}
head(pvals)
#Choi's P-value
test_stat<- -2*sum(log(na.omit(pvals)))
test_stat
#That's going to reject, but let's get a p-value for completeness
#Test is distributed chi2(2N) where N is panels
round(pchisq(test_stat, df=2*nrow(na.omit(pvals)), lower.tail = F), digits=3)
In the p-value aggregation chase, we are testing a specific null
hypothesis that all the panels have a unit root against the alternative
that at least one is stationary.
That might not be the most reassuring rejection; other tests have
different nulls.
First Differencing
The panel ADF didn’t indicate a need for differencing, but let’s to
illustrate.
(Usual caveats here; first differencing is only appropriate for I(1)
series, you need to test the differenced series for stationarity,
etc.)
#Difference these out to be safe
fd<-pdata.frame(data, index = c("ccode", "year"))
fd$d_lmilex=diff(fd$LMILEX)
fd$d_polyarchy=diff(fd$v2x_polyarchy)
fd %>%
dplyr::select(c(ccode, year, d_lmilex, d_polyarchy)) %>%
filter(ccode %in% seq(2,99,1)) %>%
pivot_longer(cols = c(d_lmilex, d_polyarchy), values_to = "values")%>%
ggplot(aes(y=values, x=year, color=as.factor(ccode)))+
geom_point()+
facet_wrap(~name, scales="free_y")
Static
More details in De Boef and Keele (2008)
static<-lm(d_lmilex~d_polyarchy, data=fd)
summary(static)
#Illustrate the impact of 1 SD change in polyarchy (temporary)
time<-seq(1,10,1)
dem<-c(rep(0,2),
sd(na.omit(fd$d_polyarchy)),
rep(0, 7))
pred_dat<-cbind.data.frame(time,dem)
pred_dat$milex_hat<-pred_dat$dem*coef(static)[2]
pred_dat %>%
ggplot(aes(x=time, y=milex_hat))+
geom_line()
If the regression equation is \(Y_t=\beta_0+\beta_1X_t+\epsilon_t\)
The effect of \(X_t\) on \(Y_t\) is \(\frac{\delta Y_t}{\delta X_t}\) which is
\(\beta_1\)
Moving forward one period: \(Y_{t+1}=\beta_0+\beta_1X_{t+1}+\epsilon_{t+1}\)
The derivative of that regression with respect to \(X_t\) is zero.
Finite Lag
fd$lag_polyarchy=lag(fd$d_polyarchy)
fd$lag_lmilex=lag(fd$d_lmilex)
lag1<-lm(d_lmilex~d_polyarchy+lag_polyarchy, data=fd)
summary(lag1)
pred_dat<-pred_dat %>%
mutate(lag_dem=dplyr::lag(dem))
pred_dat$milex_hat<-pred_dat$dem*coef(lag1)[2]+pred_dat$lag_dem*coef(lag1)[3]
pred_dat %>%
ggplot(aes(x=time, y=milex_hat))+
geom_line()
If the regression equation is \(Y_t=\beta_0+\beta_1X_t+\beta_2X_{t-1}+\epsilon_t\)
The effect of \(X_t\) on \(Y_t\) is \(\frac{\delta}{\delta X}
\beta_0+\beta_1X_t+\beta_2X_{t-1}+\epsilon_t\) which is \(\beta_1\)
Moving forward one period: \(Y_{t+1}=\beta_0+\beta_1X_{t+1}+\beta_2X_t+\epsilon_{t+1}\)
The derivative of that regression with respect to \(X_t\) is \(\beta_2\)
Derivative in periods beyond \(t+1\)
is zero as before.
Lagged Dependent Variable Models
ldv<-lm(d_lmilex~lag_lmilex+d_polyarchy, data=fd)
summary(ldv)
pred_dat[1:3,]$milex_hat<-coef(ldv)[3]*pred_dat[1:3,]$dem
pred_dat[4:10,]$milex_hat<-coef(ldv)[2]^(pred_dat[4:10,]$time-3)*coef(ldv)[3]*pred_dat[3,"dem"]
pred_dat %>%
ggplot(aes(x=time, y=milex_hat))+
geom_line()
#What about a permanent shift?
coef(ldv)
lrm<-coef(ldv)[3]*sd(na.omit(fd$d_polyarchy))/(1-coef(ldv)[2])
lrm
In the case of a temporary shock to X, the effect decays
geometrically by assumption (e.g., forced by the assumption of the
model)
To see that, let’s consider the effect of \(X_t\) at time \(t+1\) and \(t+2\)
The general equation \(Y_{t}=\beta_0+\alpha
Y_{t-1}+\beta_1X_{t}+\epsilon_{t}\)
At \(t+1\) we have
\(Y_{t+1}=\beta_0+\alpha
Y_{t}+\beta_1X_{t+1}+\epsilon_{t+1}\)
Substitute for \(Y_t\) - drop out
the error terms, constant for ease
\(Y_{t+1}=\alpha(\alpha
Y_{t-1}+\beta_1X_{t})+\beta_1X_{t+1}\)
First derivative with respect to \(X_t\) is \(\alpha\times\beta_1\)
This makes intuitive sense - \(X_t\)
affects \(Y_t\) by \(\beta_1\). In turn, \(Y_t\) affects \(Y_{t+1}\) by \(\alpha\), the extent to which \(Y\) is serially correlated.
Similarly at \(t+2\)
\(Y_{t+2}=\beta_0+\alpha
Y_{t+1}+\beta_1X_{t+2}+\epsilon_{t+2}\)
Substitute for \(Y_{t+1}\)
\(Y_{t+2}=\beta_0+\alpha (\alpha
Y_{t}+\beta_1X_{t+1})+\beta_1X_{t+2}+\epsilon_{t+2}\)
And again for \(Y_{t}\)
\(Y_{t+2}=\beta_0+\alpha [\alpha(\alpha
Y_{t-1}+\beta_1X_{t})+\beta_1X_{t+1}]+\beta_1X_{t+2}+\epsilon_{t+2}\)
This is kind of ugly, but anything that’s not multiplied by \(X_t\) can go away, which is basically
everything
We’re left with \(\alpha^2 \times
\beta_1\)
Generalizes: the effect of \(X_t\)
any arbitrary leads into the future is going to be \(\alpha^d \times \beta_1\) where \(d\) is however many leads we want.
Note that the effect of \(X_t\)
decays because of the requirement that \(\vert
\alpha \vert < 1\) - otherwise the effect does not decay at
all (\(= 1\)) or increases in time
(\(>1\)).
Serial correlation in error term
Haven’t made too much of this until now.
In general, serial correlation in the error is not a big issue (no
bias / inconsistency).
We do get bad SE/t-stats under serial correlation.
Two approaches:
Just use OLS and clean up the SEs to be robust to serial
correlation (HAC SEs, PCSEs)
Try to better model the dynamics to eliminate serial correlation
- for example with deeper lags of \(Y\)
But, with an LDV, serial correlation in the error creates bias.
(Achen (2000), Keele and Kelly (2006))
Need to be careful to ensure no serial correlation in error term of
the model.
pbgtest(d_lmilex~lag_lmilex+d_polyarchy, data=fd, model="pooling", order=1)
ldv<-plm(d_lmilex~lag_lmilex+d_polyarchy, data=fd, model="pooling")
res_df <- data.frame(residual = residuals(ldv), attr(residuals(ldv), "index"))
res_df<- res_df %>%
left_join(fd, by=c("ccode", "year"))
res_df$lag_res <- lag(res_df$residual)
res_df<-plm::pdata.frame(res_df, index=c("ccode", "year"))
wooldridge <- plm(residual~lag_res, model="pooling", data=res_df)
wooldridge_stat <- (coef(wooldridge)[2]+.5) / (sqrt(diag(vcov(wooldridge))[2]))
round(pchisq(wooldridge_stat, 1, lower.tail = F), digits=3)
Mixed results - Breusch - Godfrey test fails to reject, Wooldridge
test rejects.
Dynamic Panel Models
If we assume unit effects that impact \(Y\) (as in the FE/RE case), the LDV model
is biased, even if we do not assume correlation between the unit effects
and included variables (Wawro (2002) is an accessible
summary).
This is because the static individual effects are relegated to the
error term. The LDV is correlated with those static unit effects, so by
putting it on the RHS we’ve created bias.
Unlike in the static case, the FE estimator is also biased. This bias
is sometimes referred to as Nickell bias after Nickell (1981).
Intuition here is that the transformed LDV and error are correlated.
The group mean of the LDV contains all realizations of \(Y\) minus the final observation of the
unit. Any \(Y_t\) is correlated with
the appropriate error \(e_t\), which is
introduced into the error term by the group difference.
Bias is decreasing in \(T\) not
\(N\) - so in short panels the bias can
be very large.
Anderson-Hsiao Estimator
- First difference the regression equation to remove correlation
between LDV and FE (note this is not group demeaning, which would
prevent valid instruments.)
First differenced LDV is still correlated with first differenced
error
But, this can be handled with standard IV approaches:
- Instrument for \(\Delta
Y_{t-1}\)
Deeper lags of \(Y\) are valid
instruments, specifically \(Y_{t-2}\)-
no need to find an instrument (although if you have one that also
works!). However, this depends on no serial correlation in the
errors.
In general, the AH estimator has been superseded by GMM estimators
that build on the deeper lag approach, so it’s typically not a named
routine. But we can estimate it by hand via standard 2SLS.
fd$l2_lmilex=lag(fd$d_lmilex, 2)
ah<-ivreg(d_lmilex~lag_lmilex+d_polyarchy| l2_lmilex+d_polyarchy, data=fd )
summary(ah)
Note that we’ve only used ivreg, which is standard 2SLS estimation
(not 2SLS with FE). This is because we’ve swept out the unit effects via
first differencing already.
References
Achen, Christopher H. 2000.
“Why Lagged Dependent Variables Can
Suppress the Explanatory Power of Other Independent Variables.”
In
Annual Meeting of the Political Methodology Section of the
American Political Science Association, UCLA, 20:7–2000. 22.
http://www-personal.umich.edu/~franzese/Achen.2000.LDVstealingExplanPower.pdf.
Choi, In. 2001. “Unit Root Tests for Panel Data.”
Journal of International Money and Finance 20 (2): 249–72.
Cook, Scott J, Jude C Hays, and Robert J Franzese. 2020. “Fixed
Effects in Rare Events Data: A Penalized Maximum Likelihood
Solution.” Political Science Research and Methods 8 (1):
92–105.
De Boef, Suzanna, and Luke Keele. 2008. “Taking Time
Seriously.” American Journal of Political Science 52
(1): 184–200.
Keele, Luke, and Nathan J Kelly. 2006. “Dynamic Models for Dynamic
Theories: The Ins and Outs of Lagged Dependent Variables.”
Political Analysis 14 (2): 186–205.
Mummolo, Jonathan, and Erik Peterson. 2018. “Improving the
Interpretation of Fixed Effects Regression Results.”
Political Science Research and Methods 6 (4): 829–35.
Mundlak, Yair. 1978. “On the Pooling of Time Series and Cross
Section Data.” Econometrica: Journal of the Econometric
Society, 69–85.
Nickell, Stephen. 1981. “Biases in Dynamic Models with Fixed
Effects.” Econometrica: Journal of the Econometric
Society, 1417–26.
Wawro, Gregory. 2002. “Estimating Dynamic Panel Data Models in
Political Science.” Political Analysis 10 (1): 25–48.
LS0tDQp0aXRsZTogIlRpbWUgU2VyaWVzIENyb3NzIFNlY3Rpb25hbCAoVFNDUykgRGF0YSBUdXRvcmlhbCINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICB0b2M6IHllcw0KICAgIGRmX3ByaW50OiBwYWdlZA0KICBwZGZfZG9jdW1lbnQ6DQogICAgdG9jOiB5ZXMNCiAgaHRtbF9ub3RlYm9vazoNCiAgICB0b2M6IHllcw0KICAgIGRmX3ByaW50OiBwYWdlZA0KZGF0ZTogIkp1bmUgMTQsIDIwMjMiDQpsaW5rLWNpdGF0aW9uczogeWVzDQpiaWJsaW9ncmFwaHk6IHJlZi5iaWINCi0tLQ0KDQojIEludHJvZHVjdGlvbg0KDQpUaGlzIHdvcmtzaG9wIG9mZmVycyBhbiBpbnRyb2R1Y3Rpb24gdG8gdGltZSBzZXJpZXMgY3Jvc3Mgc2VjdGlvbmFsIChUU0NTKSBkYXRhIHdpdGggYSBmb2N1cyBvbiBhcHBsaWNhdGlvbnMgaW4gUi4gIFNvbWUgZmFtaWxpYXJpdHkgd2l0aCB0aW1lIHNlcmllcyBjcm9zcyBzZWN0aW9uYWwgZWNvbm9tZXRyaWNzLCBhcyB3ZWxsIGFzIFIsIGlzIGFzc3VtZWQuICBXZSB3aWxsIGNvdmVyIHNvbWUgYmFzaWMgdGhlb3JldGljYWwgcmVzdWx0cywgYnV0IHRoaXMgd29ya3Nob3AgaXMgbm90IGludGVuZGVkIHRvIHN1YnN0aXR1dGUgZm9yIGEgbW9yZSBkZXRhaWxlZCB0aGVvcmV0aWNhbCB0cmVhdG1lbnQuDQoNClRoZSB3b3Jrc2hvcCBzdGFydHMgd2l0aCBzb21lIGJhc2ljIGRlc2NyaXB0aW9uIG9mIHRoZSBzdHJ1Y3R1cmUgb2YgVFNDUyBkYXRhIGFuZCB0aGUgcmlza3Mgb2YgdGhlIHBvb2xlZCAoT0xTKSBlc3RpbWF0b3IsIHRoZW4gY292ZXJzIHN0YW5kYXJkIGFwcHJvYWNoZXMgdG8gdW5pdC1sZXZlbCBoZXRlcm9nZW5laXR5OiB0aGUgZml4ZWQgZWZmZWN0ICh3aXRoaW4pIGVzdGltYXRvciwgdGhlIHJhbmRvbSBlZmZlY3QgZXN0aW1hdG9yLiAgSW50ZXJwcmV0YXRpb24gYW5kIGRyYXdiYWNrcyBvZiB0aGUgZml4ZWQgZWZmZWN0IGVzdGltYXRvciBhcmUgZGlzY3Vzc2VkLCBhcyB3ZWxsIGFzIGEgcG90ZW50aWFsIHNvbHV0aW9uIHRvIHRoZSB0aW1lIGludmFyaWFudCBjb3ZhcmlhdGUgcHJvYmxlbSB2aWEgcGVuYWxpemVkIG1heGltdW0gbGlrZWxpaG9vZC4gIFdlIHdpbGwgZGlzY3VzcyB0ZXN0aW5nIHRoZSBrZXkgYXNzdW1wdGlvbiBiZWhpbmQgdGhlIHJhbmRvbSBlZmZlY3RzIG1vZGVsLCBhbmQgaW50cm9kdWNlIHRoZSB1bmlmeWluZyAid2l0aGluLWJldHdlZW4iIG1vZGVsLiANCg0KVGhlIHNlY29uZCBzZWN0aW9uIGZvY3VzZXMgb24gaXNzdWVzIHJlbGF0ZWQgdG8gdGltZS4gIFdlIHN0YXJ0IGJ5IGNvbnNpZGVyaW5nIHRoZSBpbXBsaWNhdGlvbnMgb2YgYSBzdGF0aWMgbW9kZWwsIHRoZW4gaW5jb3Jwb3JhdGUgYmFzaWMgZHluYW1pY3MgdmlhIHRoZSBmaW5pdGUgZGlzdHJpYnV0ZWQgbGFnIGFuZCBsYWdnZWQgZGVwZW5kZW50IHZhcmlhYmxlIChMRFYpIHNwZWNpZmljYXRpb24uICBXZSBicmllZmx5IGRpc2N1c3MgdGVzdHMgZm9yIHNlcmlhbCBjb3JyZWxhdGlvbiBpbiB0aGUgbW9kZWwgZXJyb3JzLCBhcyB3ZWxsIGFzIGludHJvZHVjZSB0aGUgQW5kZXJzb24tSHNpYW8gZXN0aW1hdG9yIGZvciBGRSBlc3RpbWF0aW9uIHdpdGggYW4gTERWLg0KDQojIFNldHVwDQojIyBEb3dubG9hZHMNCltUcmFpbmluZyBSZXBvLCBpbmNsdWRpbmcgdGhpcyBmaWxlXShodHRwczovL2dpdGh1Yi5jb20vTHVjeS1GYW1pbHktSW5zdGl0dXRlL3RzY3NfZGVtby5naXQpDQoNCltSXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZykNCg0KW1JzdHVkaW8gSURFXShodHRwczovL3d3dy5yc3R1ZGlvLmNvbS9wcm9kdWN0cy9yc3R1ZGlvL2Rvd25sb2FkLykNCg0KIyMgUGFja2FnZXMNCippbnN0YWxsLnBhY2thZ2VzKCkqIGFuZCAqbGlicmFyeSgpKiBmb3IgcGFja2FnZSBkb3dubG9hZHMgYW5kIGxvYWRpbmcuICBIZXJlIHdlJ2xsIGxvYWQgc29tZSB1c2VmdWwgcGFja2FnZXMgW2MgY29udmVydHMgZWxlbWVudHMgaW50byBhIHZlY3Rvcl0NCg0KYGBge3IsIHJlc3VsdHM9J2hpZGUnLCBtZXNzYWdlPUYsIHdhcm5pbmc9Rn0NCiNpbnN0YWxsLnBhY2thZ2VzKGMoInRpZHl2ZXJzZSIsICJkYXRhLnRhYmxlIiwgInJlYWRzdGF0YTEzIiwgInBsbSIsICJiaWZlIiwgInN1cnZpdmFsIiwgImJyZ2xtMiIsICJpdnJlZyIsICJsbXRlc3QiLCAidHNlcmllcyIsICJwbG90bHkiKSkNCmxpYnJhcnkoInRpZHl2ZXJzZSIpDQpsaWJyYXJ5KCJ0c2VyaWVzIikNCmxpYnJhcnkoImRhdGEudGFibGUiKQ0KbGlicmFyeSgicmVhZHN0YXRhMTMiKQ0KbGlicmFyeSgicGxtIikNCmxpYnJhcnkoImJpZmUiKQ0KbGlicmFyeSgic3Vydml2YWwiKQ0KbGlicmFyeSgiYnJnbG0yIikNCmxpYnJhcnkoIml2cmVnIikNCmxpYnJhcnkoImxtdGVzdCIpDQpsaWJyYXJ5KCJwbG90bHkiKQ0KDQojc2V0d2QoKQ0Kc2V0LnNlZWQoMTAxNSkNCmBgYA0KIyBSZXZpZXcgb2YgT0xTIGFuZCB0aGUgTGluZWFyIE1vZGVsDQpTb21lIGNsYXJpZmljYXRpb24gb2YgdGVybWlub2xvZ3kNCg0KQSBsaW5lYXIgcmVncmVzc2lvbiBtb2RlbHMgYSBkZXBlbmRlbnQgdmFyaWFibGUgJFkkIGFzIGEgZnVuY3Rpb24gb2Ygb25lIG9yIG1vcmUgaW5kZXBlbmRlbnQgdmFyaWFibGVzICgkWCQpIGFuZCBhbiBlcnJvciB0ZXJtICRcZXBzaWxvbiQNCg0KKE9yZGluYXJ5KSBMZWFzdCBTcXVhcmVzIChPTFMvTFMpIGlzIGEgcG9wdWxhciBlc3RpbWF0b3Igb2YgdGhlIGxpbmVhciBtb2RlbCwgYnV0IG5vdCB0aGUgb25seSBlc3RpbWF0b3INCg0KUmlkZ2UgUmVncmVzc2lvbiAvIExhc3NvIGFyZSBleGFtcGxlcyBvZiBvdGhlciBlc3RpbWF0b3JzIG9mIHRoZSBsaW5lYXIgbW9kZWwNCg0KRnJvbSBhbiBNTCBwZXJzcGVjdGl2ZSwgbGluZWFyIHJlZ3Jlc3Npb24gaXMgYSBmb3JtIG9mIHN1cGVydmlzZWQgbGVhcm5pbmcgd2hpbGUgT0xTIGlzIHVzZXMgZXJyb3IgbWluaW1pemF0aW9uIGFzIG1lYXN1cmVkIGJ5IHRoZSBzdW0gb2Ygc3F1YXJlZCByZXNpZHVhbHMNCg0KIyMgSW50dWl0aW9uDQpDcmVhdGUgYSB1bml2YXJpYXRlIGxpbmVhciByZWxhdGlvbnNoaXAgdXNpbmcgYSBNb250ZSBDYXJsbyBzaW11bGF0aW9uDQoNCmBgYHtyLCB3YXJuaW5nPUYsIG1lc3NhZ2U9Rn0NCnNhbXBsZSA8LSAyMDANCnggPC0gcm5vcm0oc2FtcGxlLCAwLCAyKQ0KZSA8LSBybm9ybShzYW1wbGUsIDAgLCAxMCkNCnkgPC0gMyArIHggKyBlDQp1bml2YXJpYXRlIDwtIGRhdGEuZnJhbWUoeSwgeCkNCnVuaXZhcmlhdGUNCg0KcGxvdDwtdW5pdmFyaWF0ZSAlPiUNCiAgZ2dwbG90KGFlcyh4LCB5KSkgKw0KICBnZW9tX3BvaW50KCkNCg0KZ2dwbG90bHkocGxvdCkNCmBgYA0KDQpFc3RpbWF0aW5nIGEgdW5pdmFyaWF0ZSBsaW5lYXIgbW9kZWwgaXMgZXF1aXZhbGVudCB0byBkcmF3aW5nIGEgc3RyYWlnaHQgbGluZSB0aHJvdWdoIHRoaXMgc2NhdHRlciBwbG90DQoNCkNhbiBmaXQgYW55IG51bWJlciBvZiBsaW5lYXIgbW9kZWxzIHRvIHRoaXMgZGF0YSAtIG5lZWQgYSBjcml0ZXJpYSBmb3IgZGV0ZXJtaW5pbmcgdGhlIGJlc3QgbW9kZWwNCg0KT0xTIHBvc2l0cyB0aGF0IHRoZSBiZXN0IG1vZGVsIGlzIG9uZSB0aGF0IG1pbmltaXplcyB0aGUgZXJyb3Igb2YgdGhlIG1vZGVsJ3MgcHJlZGljdGVkICRZJCBhbmQgdGhlIHJlYWwgJFkkDQoNCk9MUyBtZWFzdXJlcyBtb2RlbCBlcnJvciBhcyB0aGUgc3VtIG9mIHNxdWFyZWQgcmVzaXVkYWxzDQoNCmBgYHtyfQ0KdW5pdmFyaWF0ZSRwcmVkIDwtIHByZWRpY3QobG0oeX54LCBkYXRhPXVuaXZhcmlhdGUpKQ0KdW5pdmFyaWF0ZSRyZXNpZCA8LSB1bml2YXJpYXRlJHkgLSB1bml2YXJpYXRlJHByZWQNCg0KcmVzaWRfcGxvdDwtdW5pdmFyaWF0ZSAlPiUNCiAgZ2dwbG90KGFlcyh4LCB5KSkgKw0KICBnZW9tX3BvaW50KCkrDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlPUYpKw0KICBnZW9tX3NlZ21lbnQoYWVzKHhlbmQ9eCwgeWVuZCA9IHByZWQpLCBjb2xvcj0icmVkIikNCg0KZ2dwbG90bHkocmVzaWRfcGxvdCkNCmBgYA0KDQojIyBGb3JtYWxpemF0aW9uDQoNCldyaXRlIHRoZSB1bmtub3duLCBidXQgbGluZWFyLCBkYXRhIGdlbmVyYXRpbmcgcHJvY2VzcyBmb3IgJFkkIGFzIA0KDQokJCBZID0gXGJldGFfMCArIFxiZXRhXzFYICsgXGVwc2lsb24gJCQNCk91ciBsaW5lYXIgbW9kZWwgcmV0dXJucyBlc3RpbWF0ZXMgb2YgY29lZmZpY2llbnRzLCAkXGJldGEkLCB3aGljaCB3ZSBkZW5vdGUgd2l0aCAkXGhhdHt9JC4gIFdlIHVzZSB0aGVzZSBlc3RpbWF0ZXMgdG8gY29uc3RydWN0IHRoZSBlc3RpbWF0ZSBvZiAkWSQNCg0KJCRcaGF0e1l9ID0gXGhhdHtcYmV0YV8wfSArIFxoYXR7XGJldGFfMX1YICQkDQpXZSBkZWZpbmUgdGhlIHJlc2lkdWFsICRlJCBhcyB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuICRZJCBhbmQgaXRzIGVzdGltYXRlICRcaGF0e1l9JCwgd2hpY2ggd2UgdXNlIGFzIGFuIGVzdGltYXRlIG9mIHRoZSB1bmtub3duIGRpc3R1cmJhbmNlICRcZXBzaWxvbiQuICBOb3RlIHRoYXQgd2UgbW92ZSB0byBlc3RpbWF0ZXMgZm9yIGFuIGluZGl2aWR1YWwgb2JzZXJ2YXRpb24gJGkkIGJlbG93Og0KDQokJCBlX2kgPSBcaGF0e3l9X2kgLSB5X2kkJA0KRmluYWxseSwgd2UgZGVub3RlIHRoZSByZXNpZHVhbCBzdW0gb2Ygc3F1YXJlcyAoUlNTKSBhcyB0aGUgc3VtIG9mIHRoZSBzcXVhcmVkIHJlc2lkdWFscyBmb3IgYWxsIG9ic2VydmF0aW9ucyBpbiB0aGUgZGF0YQ0KDQokJCBSU1MgPSBcc3VtX3tpPTF9XntufWVfaV4yJCQNCk9MUyBlc3RpbWF0ZXMgdGhlIGNvZWZmaWNpZW50cyAkXGJldGEkIHRoYXQgbWluaW1pemUgJFJTUyQuICBGb3IgdGhlIHNpbXBsZSBiaXZhcmlhdGUgY2FzZSB0aGUgY29lZmZpY2llbnQgb24gJFgkIGlzIHNpbXBseSB0aGUgcmF0aW8gb2YgaXQncyBjb3ZhcmlhbmNlIHdpdGggJFkkIG92ZXIgaXRzIHZhcmlhbmNlOg0KDQokJFxoYXR7XGJldGFfMX0gPSBcZnJhY3tcc3VtX3tpPTF9XntufSh4X2kgLSBcb3ZlcmxpbmV7eH0pKHlfaSAtIFxvdmVybGluZXt5fSl9e1xzdW1fe2k9MX1ee259KHhfaSAtIFxvdmVybGluZXt4fSleMn0kJA0KVGhlIGNvbnN0YW50IGlzIHNpbXBseSB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBtZWFuIG9mICRZJCBhbmQgdGhlIHByZWRpY3RlZCAkWSQgYXQgdGhlIG1lYW4gb2YgJFgkDQoNCiQkXGhhdHtcYmV0YV8wfSA9IFxvdmVybGluZXt5fSAtIFxoYXR7XGJldGFfMX1cb3ZlcmxpbmV7eH0kJA0KR2l2ZW4gdGhhdCB0aGUgY29lZmZpY2llbnQgZXN0aW1hdGVzIHRoYXQgbWluaW1pemUgJFJTUyQgYXJlIGtub3duIHRoZXJlIGlzIG5vIG5lZWQgdG8gcGVyZm9ybSBtb2RlbCB0cmFpbmluZyBvciB0dW5pbmcgdG8gZXN0aW1hdGUgdGhlbSAtIHRoZXkgY2FuIGJlIGNhbGN1bGF0ZWQgZGlyZWN0bHkgZnJvbSB0aGUgZGF0YQ0KDQpgYGB7cn0NCmNvZWYobG0oeX54LCBkYXRhPXVuaXZhcmlhdGUpKQ0KDQptZWFuX3ggPC0gbWVhbih4KQ0KbWVhbl95IDwtIG1lYW4oeSkNCmJldGExX2hhdCA8LShzdW0oKHVuaXZhcmlhdGUkeCAtIG1lYW5feCkqKHVuaXZhcmlhdGUkeSAtIG1lYW5feSkpKS8oc3VtKCh1bml2YXJpYXRlJHgtbWVhbl94KV4yKSkNCmJldGEwX2hhdCA8LSBtZWFuX3kgLSBiZXRhMV9oYXQqbWVhbl94DQpwcmludChjKGJldGEwX2hhdCwgYmV0YTFfaGF0KSkNCmBgYA0KDQojIyBXaGF0J3MgU3BlY2lhbCBBYm91dCBSU1M/DQpVbmRlciBjZXJ0YWluIGFzc3VtcHRpb25zLCBPTFMgaXMgdGhlICdiZXN0JyBlc3RpbWF0b3IgZm9yIHRoZSBsaW5lYXIgbW9kZWwNCg0KKlplcm8gY29uZGl0aW9uYWwgbWVhbiBhc3N1bXB0aW9uKiAoYWxvbmcgd2l0aCBzb21lIG90aGVyIHRlY2huaWNhbCBhc3N1bXB0aW9ucykgaXMgc3VmZmljaWVudCB0byBlbnN1cmUgdW5iaWFzZWRuZXNzICgkRShcaGF0e1xiZXRhfSk9XGJldGEkKToNCg0KJCRFKFxlcHNpbG9ufFgpID0gMCAkJA0KTm90ZSB0aGF0IHRoaXMgaXMgYW4gYXNzdW1wdGlvbiBhYm91dCB0aGUgdW5vYnNlcnZlZCBlcnJvciAkXGVwc2lsb24kIGFuZCBjYW5ub3QgYmUgdGVzdGVkIC0gT0xTIHdpbGwgZml0IHJlc2lkdWFsICRlJCB0aGF0IGlzIG1lYW4gemVybyB3aGV0aGVyIG9yIG5vdCBpdCdzIGFwcHJvcHJpYXRlDQoNClRoZSBhZGRpdGlvbmFsIGFzc3VtcHRpb24gb2YgKkhvbW9za2VkYXN0aWMgYW5kIFNlcmlhbGx5IFVuY29ycmVsYXRlZCBFcnJvcnMqIG1ha2VzIE9MUyB0aGUgTWluaW11bSBWYXJpYW5jZSBVbmJpYXNlZCBMaW5lYXIgRXN0aW1hdG9yDQoNCiQkVmFyKFxlcHNpbG9uIHwgWCkgPSBcc2lnbWFeMiAkJA0KJCRDb3JyKFxlcHNpbG9uX3QsIFxlcHNpbG9uX3MpID0gMCwgXGZvcmFsbCB0IFxuZXEgcyAkJA0KSW5mb3JtYWxseSwgdGhlc2UgdHdvIGFzc3VtcHRpb25zIGVuc3VyZSB0aGF0IG9mIGFsbCB0aGUgdW5iaWFzZWQgbGluZWFyIGVzdGltYXRvcnMgb2YgdGhlIGxpbmVhciBtb2RlbCwgT0xTIGhhcyB0aGUgc21hbGxlc3QgdmFyaWFuY2UNCg0KVGhpcyBkb2VzIG5vdCBtZWFuIE9MUyBpcyB0aGUgYWJzb2x1dGUgYmVzdCBtb2RlbCBpbiBhbnkgY2lyY3Vtc3RhbmNlIA0KDQpJZiB0aGUgc3RhbmRhcmQgZXJyb3JzIHNhdGlzZnkgdGhlIGFib3ZlIGFzc3VtcHRpb25zLCBidXQgYXJlIG5vdCBub3JtYWxseSBkaXN0cmlidXRlZCwgdGhlbiBub24tbGluZWFyIHVuYmlhc2VkIGVzdGltYXRvcnMgbWF5IG9mZmVyIGltcHJvdmVtZW50LCBzdWNoIGFzIHRyaW1tZWQgbGVhc3Qgc3F1YXJlcw0KDQpWYXJpYW5jZSBtYXkgYmUgcmVkdWNlZCBieSB1c2luZyBhIGJpYXNlZCBlc3RpbWF0b3IsIHN1Y2ggYXMgcmlkZ2UgcmVncmVzc2lvbg0KDQojIyBDb2VmZmljaWVudCBWYXJpYW5jZQ0KDQpPTFMgaXMgdW5iYWlzZWQsIGJ1dCBhbnkgaW5kaXZpZHVhbCBlc3RpbWF0ZSBvZiAkXGhhdFxiZXRhJCBtYXkgYmUgZmFyIGZyb20gJFxiZXRhJA0KDQpUaGUgdmFyaWFuY2Ugb2YgJFxoYXRcYmV0YV8xJCBpcyBhIGZ1bmN0aW9uIG9mIHRoZSB2YXJpYW5jZSBvZiB0aGUgZXJyb3IgYW5kIHRoZSB2YXJpYW5jZSBvZiAkWCQNCg0KSGlnaGVyIHZhcmlhbmNlIGluIHRoZSBlcnJvciBtYWtlcyBlc3RpbWF0aW9uIGxlc3MgcHJlY2lzZSB3aGlsZSBoaWdoZXIgdmFyaWFuY2UgaW4gJFgkIG1ha2VzIGl0IG1vcmUgcHJlY2lzZToNCg0KJCQgVmFyKFxoYXRcYmV0YV8xKSA9IFxmcmFje1xzaWdtYV4yfXtcc3VtX3tpPTF9Xm4oeF9pLVxvdmVybGluZXt4fSleMn0gJCQNCkRlbm9taW5hdG9yIGlzIGtub3duIGFzIGEgZnVuY3Rpb24gb2YgdGhlIGRhdGEgLSBudW1lcmF0b3IgaXMgdW5rbm93biBhbmQgbXVzdCBiZSBlc3RpbWF0ZWQNCg0KQW4gdW5iaWFzZWQgZXN0aW1hdG9yIG9mICRcc2lnbWFeMiQgaXMgJFJTUy8obi0yKSQgd2hlcmUgJG4tMiQgaXMgYSBkZWdyZWVzIG9mIGZyZWVkb20gYWRqdXN0bWVudCBkdWUgdG8gY29uc3RyYWludHMgb2YgT0xTDQoNCkZvciB0ZXN0IHN0YXRpc3RpY3MsIHdlIHdvcmsgd2l0aCB0aGUgc3RhbmRhcmQgZXJyb3Igb2YgdGhlIGNvZWZmaWNpZW50LCBhcyBvcHBvc2VkIHRvIHRoZSB2YXJpYW5jZQ0KDQokJHNlKFxoYXRcYmV0YV8xKSA9IFxzcXJ0XGZyYWN7XHNpZ21hXjJ9e1xzdW1fe2k9MX1ebih4X2ktXG92ZXJsaW5le3h9KV4yfSA9IFxzcXJ0XGZyYWN7UlNTLyhuLTIpfXtcc3VtX3tpPTF9Xm4oeF9pLVxvdmVybGluZXt4fSleMn0gJCQNCg0KIyMgTXVsdGlwbGUgUmVncmVzc2lvbg0KDQpDb25zaWRlciBhIGxpbmVhciBtb2RlbCB3aGVyZSAkWSQgaXMgYSBmdW5jdGlvbiBvZiB0d28gaW5kZXBlbmRlbnQgdmFyaWFibGVzOg0KDQokJFkgPSBcYmV0YV8wICsgXGJldGFfMSBYXzEgKyBcYmV0YV8yIFhfMiArIFxlcHNpbG9uJCQNCmBgYHtyfQ0KeDEgPC0gcm5vcm0oc2FtcGxlLCAwLCA1KQ0KeDIgPC0gMip4MSArIHJub3JtKHNhbXBsZSwgMCwgNSkNCnkgPC0gMip4MS14Mitybm9ybShzYW1wbGUsIDAsNSkNCg0KbXVsdGl2YXJpYXRlIDwtIGRhdGEuZnJhbWUoeDEsIHgyLCB5KQ0KDQptdWx0aV9wbG90PC1wbG90X2x5KG11bHRpdmFyaWF0ZSwgeCA9IH54MSwgeSA9IH54MiwgeiA9IH55KQ0KbXVsdGlfcGxvdDwtbXVsdGlfcGxvdCAlPiUNCiAgYWRkX21hcmtlcnMoKQ0KbXVsdGlfcGxvdA0KYGBgDQoNCkVzdGltYXRpb24gb2YgdGhpcyBsaW5lYXIgbW9kZWwgdmlhIE9MUyBpcyBzaW1pbGFyDQoNClJlY2FsbCBPTFMgbWluaW1pemVzICRSU1MkDQoNCiQkIFJTUyA9IFxzdW1fe2k9MX1ee259ZV9pXjIkJA0KJCQgPSBcc3VtX3tpPTF9XntufShcaGF0e3lfaX0gLSB5X2kpXjIgJCQNCiQkID0gXHN1bV97aT0xfV57bn0oKFxoYXR7XGJldGFfMH0gKyBcaGF0e1xiZXRhXzF9WF97MWl9ICsgXGhhdHtcYmV0YV8yfVhfezJpfSkgLSB5X2kpXjIgJCQNCldoZW4gd2UgbW9kZWwgJFkkIGFzIGEgZnVuY3Rpb24gb2YgJFhfMiQgT0xTIG1pbmltaXplcyAkUlNTJCBvdmVyIGJvdGggJFgkDQoNClRoZSBmb3JtdWxhIGZvciBjb2VmZmljaWVudHMgb2YgbXVsdGl2YXJpYXRlIHJlZ3Jlc3Npb24gYXJlIG1vcmUgY29tcGxpY2F0ZWQsIGJ1dCBvbmUgcmVwcmVzZW50YXRpb246DQoNCiQkXGhhdFxiZXRhXzEgPSBcZnJhY3tcc3VtX3tpPTF9XntufVxoYXR7cl97aTF9fXlfaX17XHN1bV97aT0xfV57bn0oXGhhdHtyX3tpMX19KV4yfSAkJA0KV2hlcmUgJFxoYXR7cl97aTF9fSQgaXMgdGhlIHJlc2lkdWFsIGZyb20gdGhlIGF1eGlsaWFyeSByZWdyZXNzaW9uIG9mICRYMSQgb24gJFgyJA0KDQokJCBYXzEgPSBcaGF0XGdhbW1hXzArXGhhdFxnYW1tYV8xe1hfMn0gKyBcaGF0e3JfMX0gJCQNCk5vdGUgdGhhdCBvdXIgbmV3IGVzdGltYXRlIGZvciAkXGhhdFxiZXRhXzEkIGlzIGlkZW50aWNhbCB0byBvdXIgb2xkIGVzdGltYXRlIGV4Y2VwdCB0aGF0ICRDb3YoXGhhdHtyfSwgeSkkIGFuZCAkVmFyKFxoYXR7cn0pJCBoYXZlIHJlcGxhY2VkICRDb3Z7eCwgeX0kIGFuZCAkVmFyKHgpJCByZXNwZWN0aXZlbHkNCg0KVGhlIHNwZWNpZmljIGZvcm0gb2YgdGhlc2UgdmFyaWFuY2VzIGFuZCBjb3ZhcmlhbmNlcyBpcyBzbGlnaHRseSBkaWZmZXJlbnQgLSBub3RlIG5vIG1lYW5zISBXZSd2ZSBhcHBsaWVkIHR3byBzaW1wbGlmaWNhdGlvbnMgdG8gZHJvcCBtZWFucw0KDQokJCBFW1xoYXR7cn1dID0gMCAkJA0KDQokJCBDb3YoeCwgeSkgPSBcc3VtX3tpPTF9XntufSh4X2kgLSBcb3ZlcmxpbmV7eH0pKHlfaSAtIFxvdmVybGluZXt5fSkgPSBcc3VtX3tpPTF9XntufSh4X2kgLSBcb3ZlcmxpbmV7eH0peV9pICQkDQoNCiMjIyBJbGx1c3RyYXRpb24gb2YgTXVsdGlwbGUgUmVncmVzc2lvbiBieSBQYXJ0aWFsIFJlZ3Jlc3Npb24NCg0KYGBge3J9DQptdWx0aXZhcmlhdGUkcmVzaWQgPC0gcmVzaWR1YWxzKGxtKHgxfngyLCBtdWx0aXZhcmlhdGUpKQ0KcGFydGlhbCA8LSBsbSh5fnJlc2lkLCBtdWx0aXZhcmlhdGUpDQpmdWxsIDwtIGxtKHl+eDEreDIsIG11bHRpdmFyaWF0ZSkNCg0KcHJpbnQoYyhjb2VmKHBhcnRpYWwpLCBjb2VmKGZ1bGwpKSkNCmBgYA0KIyMjIElsbHVzdHJhdGlvbiBvZiBPbWl0dGVkIFZhcmlhYmxlIEJpYXMNCmBgYHtyfQ0Kc2hvcnQgPC0gbG0oeX54MSwgbXVsdGl2YXJpYXRlKQ0KcHJpbnQoY29lZihzaG9ydCkpDQphdXggPC0gbG0oeDJ+eDEsIG11bHRpdmFyaWF0ZSkNCmNvZWYoZnVsbClbMl0gKyBjb2VmKGZ1bGwpWzNdKmNvZWYoYXV4KVsyXQ0KDQpgYGANCg0KIyBGcmVxdWVudGlzdCBTdGF0aXN0aWNhbCBJbmZlcmVuY2UNCkZ1bmRhbWVudGFsIHF1ZXN0aW9uOiBkb2VzICRYJCBlZmZlY3QgJFkkPw0KDQpGcmVxdWVudGlzdCBpbmZlcmVuY2UgYmVnaW5zIGJ5IGFzc3VtaW5nIHRoZSBvcHBvc2l0ZS4gV2UgcmVmZXIgdG8gdGhpcyBhcyB0aGUgbnVsbCBoeXBvdGhlc2lzOg0KDQokSF8wJDogVGhlcmUgaXMgbm8gcmVsYXRpb25zaGlwIGJldHdlZW4gJFgkIGFuZCAkWSQNCg0KVW5kZXIgdGhlIG51bGwgaHlwb3RoZXNpcyAtIHdoYXQgZG8gd2UgZXhwZWN0ICRcaGF0XGJldGFfMSQgdG8gYmU/DQoNClN0YXRpc3RpY2FsbHksIHdlIHdhbnQgdG8gdGVzdCBob3cgbGlrZWx5IG91ciBlc3RpbWF0ZSBvZiAkXGhhdFxiZXRhXzEkIHVuZGVyIHRoZSBudWxsIGh5cG90aGVzaXMgLSBpbiBvdGhlciB3b3JkcyBpZiB0aGUgZWZmZWN0IG9mICRYJCBpcyB6ZXJvLCBob3cgdW5saWtlbHkgaXMgb3VyIGVzdGltYXRlPw0KDQpUaGlzIGRlcGVuZHMgb24gdGhlIGNvZWZmaWNpZW50IGFuZCBpdCdzIHZhcmlhbmNlLCB3aGljaCB3ZSB1c2UgdG8gY29uc3RydWN0IGEgdC1zdGF0aXN0aWM6DQoNCiQkdCA9IFxmcmFje1xoYXRcYmV0YV8xIC0gXGJldGFfezF8SF8wfX17c2UoXGhhdFxiZXRhXzEpfSAkJA0KDQpVbmRlciB0aGUgKm5vcm1hbGl0eSBhc3N1bXB0aW9uKjoNCg0KJCQgXGVwc2lsb24gXHNpbSBOb3JtYWwoMCwgXHNpZ21hXjIpICQkDQoNClRoZSB0LXN0YXRpc3RpYyBmb2xsb3dzIGEgdC1kaXN0cmlidXRpb24gd2l0aCBuLWstMSBkZWdyZWVzIG9mIGZyZWVkb20uIEtub3dpbmcgdGhpcyB3ZSBjYW4gY2FsY3VsYXRlIGEgKnAtdmFsdWUqIHdoaWNoIHJlcHJlc2VudHMgdGhlIHByb2JhYmlsaXR5IHRoYXQgd2UgY291bGQgZHJhdyBhIHRlc3Qgc3RhdGlzdGljIGF0IGxlYXN0IGFzIGxhcmdlIGFzICRUJCAob25lIHRhaWxlZCB0ZXN0KSBvciBhdCBsZWFzdCBhcyBsYXJnZSBhcyAkfFR8JCAodHdvIHRhaWxlZCkNCg0KTm90ZSB0aGF0IG5vcm1hbGl0eSBpbXBsaWVzIGhvbW9za2VkYXN0aWNpdHkNCg0KIyMgTWFudWFsIElsbHVzdHJhdGlvbg0KYGBge3J9DQp1bml2YXJpYXRlJHlfaGF0ID0gYmV0YTBfaGF0ICsgYmV0YTFfaGF0ICogdW5pdmFyaWF0ZSR4DQpyc3MgPSBzdW0oKHVuaXZhcmlhdGUkeV9oYXQgLSB1bml2YXJpYXRlJHkpXjIpDQpzZV9iZXRhMSA8LSBzcXJ0KA0KICAocnNzLyhzYW1wbGUtMikpLw0KICAgIHN1bSgodW5pdmFyaWF0ZSR4IC0gbWVhbl94KV4yKQ0KICApDQp0IDwtIGJldGExX2hhdC9zZV9iZXRhMQ0KcCA8LSAyKnB0KGFicyh0KSwgZGY9c2FtcGxlLTIsIGxvd2VyPUYpDQpwcmludChjKHQsIHApKQ0KYGBgDQojIyBMTSBGdW5jdGlvbg0KYGBge3J9DQpsbSA8LSBsbSh5fngsIGRhdGE9dW5pdmFyaWF0ZSkNCnN1bW1hcnkobG0pDQpwbG90KGxtKQ0KYGBgDQoNCiMgVFNDUyBEYXRhDQpUU0NTIGRhdGEgaGF2ZSBvYnNlcnZhdGlvbnMgb2YgbXVsdGlwbGUgdW5pdHMgKk4qIG92ZXIgdGltZSAqVCouDQoNCkVhY2ggc3BlY2lmaWMgb2JzZXJ2YXRpb24gd2l0aGluIHRoZSBkYXRhIGlzIG9mIG9uZSB1bml0IGF0IG9uZSB0aW1lLCBlLmcuDQoNCmBgYHtyLCB3YXJuaW5nPUYsIG1lc3NhZ2U9Rn0NCmRhdGE8LXJlYWQuZHRhMTMoIm1zX21pbF9zcGVuZF9kYXRhLmR0YSIpDQpkYXRhICU+JQ0KICBmaWx0ZXIoY2NvZGU9PTIsIHllYXI9PTIwMDApDQpgYGANClRoaXMgb2JzZXJ2YXRpb24gaXMgZm9yIHRoZSBVUyAoMikgZm9yIHRoZSB5ZWFyIDIwMDAuDQoNCmBgYHtyfQ0KZGF0YSAlPiUgDQogIGRwbHlyOjphcnJhbmdlKGNjb2RlLCB5ZWFyKSAlPiUNCiAgZHBseXI6OnNlbGVjdChjY29kZSwgeWVhciwgTE1JTEVYLCB2MnhfcG9seWFyY2h5KQ0KDQpkYXRhICU+JQ0KICBkcGx5cjo6ZmlsdGVyKGNjb2RlICVpbiUgYygyLDIwKSkgJT4lDQogIGdncGxvdChhZXMoeD15ZWFyLCB5PUxNSUxFWCkpICsNCiAgZ2VvbV9saW5lKCkgKw0KICBmYWNldF93cmFwKH5jY29kZSkNCmBgYA0KDQojIFdpdGhpbiAvIEJldHdlZW4gRGVjb21wb3NpdGlvbg0KDQpgYGB7cn0NCnN1bW1hcnkoZGF0YSRMTUlMRVgpDQoNCiNCZXR3ZWVuIHVuaXQgdmFyaWF0aW9uDQpkYXRhICU+JQ0KICBncm91cF9ieShjY29kZSkgJT4lDQogIHN1bW1hcml6ZShiZXR3ZWVuPW1lYW4obmEub21pdChMTUlMRVgpKSklPiUNCiAgZHBseXI6OnNlbGVjdChiZXR3ZWVuKSAlPiUNCiAgdW5ncm91cCgpICU+JQ0KICBzdW1tYXJ5KCkNCg0KI1dpdGhpbiB1bml0IHZhcmlhdGlvbg0KZGF0YSAlPiUNCiAgZ3JvdXBfYnkoY2NvZGUpICU+JQ0KICBtdXRhdGUoYmV0d2Vlbj1tZWFuKG5hLm9taXQoTE1JTEVYKSksDQogICAgICAgICB3aXRoaW49TE1JTEVYLW1lYW4obmEub21pdChMTUlMRVgpKSkgJT4lDQogIGRwbHlyOjpzZWxlY3Qod2l0aGluKSAlPiUNCiAgdW5ncm91cCgpICU+JQ0KICBzdW1tYXJ5KCkNCmBgYA0KDQojIFBvb2xpbmcNClRoZSBzaW1wbGVzdCBhcHByb2FjaCB0byBlc3RpbWF0aW5nIGEgbW9kZWwgb24gVFNDUyBpcyB0byBwb29sIHRoZSBkYXRhOg0KDQokWV97aXR9PVxiZXRhXzArXGJldGFfMVhfe2l0fStlX3tpdH0kDQoNCldoZXJlIFkgaXMgdGhlIERWLCBYIGlzIHRoZSBJViwgJFxiZXRhXzAkIGlzIHRoZSBpbnRlcmNlcHQsICRcYmV0YV8xJCBpcyB0aGUgY29lZmZpY2llbnQgb24gWCBhbmQgJGVfe2l0fSQgaXMgdGhlIGVycm9yLg0KDQpXaGF0IGFyZSB3ZSBhc3N1bWluZyBoZXJlPw0KDQpBbGwgb2YgdGhlICROJCB1bml0cyBzaGFyZSBhIGNvbW1vbiBpbnRlcmNlcHQgJFxiZXRhXzAkIGFuZCBhIGNvbW1vbiBzbG9wZSAkXGJldGFfMSQgb24gWC4NCg0KU3RhbmRhcmQgT0xTIGFzc3VtcHRpb25zIHJlZ2FyZGluZyB0aGUgZXJyb3IgdGVybSAoc3BlY2lmaWNhbGx5IHplcm8gY29uZGl0aW9uYWwgbWVhbiBhbmQgd2hpdGUgbm9pc2UgZXJyb3JzKS4NCg0KV2hldGhlciBwb29saW5nIGlzIGFwcHJvcHJpYXRlIGRlcGVuZHMgb24gd2hldGhlciB0aG9zZSBhc3N1bXB0aW9ucyBhcmUgY29ycmVjdC4NCg0KIyMgQ2xlYW4gUG9vbA0KYGBge3J9DQojTW9udGUgQ2FybG8gc2ltdWxhdGlvbnMgdG8gYmV0dGVyIGNvbnRyb2wgdGhlIHJlbGF0aW9uc2hpcHMNCk48LXNlcSgxLDUsMSkNClRpbWU8LXNlcSgxLDUwLDEpDQpjbGVhbjwtZXhwYW5kLmdyaWQoTiwgVGltZSkNCm5hbWVzKGNsZWFuKTwtYygiTiIsICJUaW1lIikNCmNsZWFuPC0gY2xlYW4gJT4lIA0KICBkcGx5cjo6YXJyYW5nZShOLCBUaW1lKQ0KDQp0aWJibGUoY2xlYW4pDQoNCiNEcmF3IHRoZSBJViwgRFYsIGVycm9yDQpjbGVhbiRYPC1ybm9ybShucm93KGNsZWFuKSwgMSwgLjI1KQ0KY2xlYW4kWTwtMy0yKmNsZWFuJFgrcm5vcm0obnJvdyhjbGVhbiksIDAsIC41KQ0KdGliYmxlKGNsZWFuKQ0KI1J1biB0aGUgcG9vbGVkIG1vZGVsDQpjbGVhbl9wb29sPC1sbShZflgsIGRhdGE9Y2xlYW4pDQpzdW1tYXJ5KGNsZWFuX3Bvb2wpDQoNCiNQbG90IHRvIHVuZGVyc3RhbmQgd2h5IHRoaXMgd29ya2VkDQpjbGVhbiAlPiUNCiAgZ2dwbG90KGFlcyh4PVgsIHk9WSkpKw0KICBnZW9tX3BvaW50KGFlcyhjb2xvcj1hcy5mYWN0b3IoTikpKSsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kPSJsbSIsIHNlPUYpDQoNCmBgYA0KDQpQb29sZWQgbW9kZWwgd29ya3MgaGVyZSBiZWNhdXNlIHRoZXJlIGlzIG5vIGRpZmZlcmVuY2UgaW4gdGhlIHVuZGVybHlpbmcgcmVsYXRpb25zaGlwIC0gd2Uga25vdyB0aGlzIGJlY2F1c2Ugd2UgZHJldyBYIHdpdGhvdXQgcmVzcGVjdCB0byBOLCBUaW1lDQoNCiMjIERpcnR5IFBvb2wNCg0KTGV0J3MgYXNzdW1lIGluc3RlYWQgdGhhdCB0aGVyZSBleGlzdHMgc29tZSB1bml0LWxldmVsIGhldGVyb2dlbmVpdHkuICBTb21lICRaJCBhZmZlY3RzIGJvdGggJFkkIGFuZCAkWCQgYnV0IGlzIHRpbWUgY29uc3RhbnQuDQoNCllvdSBtYXkgcmVjb2duaXplIHRoaXMgYXMgdGhlIHNldHVwIGZvciBvbWl0dGVkIHZhcmlhYmxlIGJpYXMuDQoNCmBgYHtyfQ0KI01vbnRlIENhcmxvIHNpbXVsYXRpb25zIHRvIGJldHRlciBjb250cm9sIHRoZSByZWxhdGlvbnNoaXBzDQpOPC1zZXEoMSw1LDEpDQpUaW1lPC1zZXEoMSw1MCwxKQ0KZGlydHk8LWV4cGFuZC5ncmlkKE4sIFRpbWUpDQpuYW1lcyhkaXJ0eSk8LWMoIk4iLCAiVGltZSIpDQpkaXJ0eTwtIGRpcnR5ICU+JSANCiAgZHBseXI6OmFycmFuZ2UoVGltZSwgTikNCg0KI0RyYXcgdGhlIHVub2JzZXJ2ZWQgZWZmZWN0LCBJViwgRFYsIGVycm9yDQpaPC1ybm9ybShsZW5ndGgodW5pcXVlKGRpcnR5JE4pKSwgMCwgLjUpDQpkaXJ0eSRaPC1yZXAoWiwgbGVuZ3RoKFRpbWUpKQ0KZGlydHkkWDwtZGlydHkkWitybm9ybShucm93KGRpcnR5KSwgMSwgLjI1KQ0KZGlydHkkWTwtMy0yKmRpcnR5JFgrNCpkaXJ0eSRaK3Jub3JtKG5yb3coZGlydHkpLDAsIC41KQ0KDQojUnVuIHRoZSBwb29sZWQgbW9kZWwNCmRpcnR5X3Bvb2w8LWxtKFl+WCwgZGF0YT1kaXJ0eSkNCnN1bW1hcnkoZGlydHlfcG9vbCkNCg0KI1Bsb3QgdGhlIHBvb2xlZCBtb2RlbCAtIHdoYXQgYXJlIHdlIGxvb2tpbmcgYXQ/DQoNCmRpcnR5ICU+JQ0KICBnZ3Bsb3QoYWVzKHg9WCwgeT1ZKSkrDQogIGdlb21fcG9pbnQoKSsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kPSJsbSIsIHNlPUYpDQoNCmRpcnR5ICU+JQ0KICBnZ3Bsb3QoYWVzKHg9WCwgeT1ZKSkrDQogIGdlb21fcG9pbnQoYWVzKGNvbG9yPWFzLmZhY3RvcihOKSkpKw0KICBnZW9tX3Ntb290aChtZXRob2Q9ImxtIiwgc2U9RikNCg0KI1Bsb3QgdGhlIHBlciB1bml0IHJlZ3Jlc3Npb25zDQpkaXJ0eSAlPiUNCiAgZ2dwbG90KGFlcyh4PVgsIHk9WSwgY29sb3I9YXMuZmFjdG9yKE4pKSkrDQogIGdlb21fcG9pbnQoKSsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kPSJsbSIsIHNlPUYpDQoNCmBgYA0KDQpJbiB0aGlzIGNhc2UsIHBvb2xpbmcgZXN0aW1hdGVzIGEgd2VhayBwb3NpdGl2ZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBYIGFuZCBZLCBkZXNwaXRlIHRoZSBmYWN0IHRoYXQgdGhlIHRydWUgcmVsYXRpb25zaGlwIGlzIG5lZ2F0aXZlLg0KDQpUaGlzIG9jY3VycyBiZWNhdXNlIHRoZXJlIGlzIG9taXR0ZWQgdmFyaWFibGUgYmlhcyBpbnRyb2R1Y2VkIGJ5IFouDQoNCk5vdGUgdGhhdCBwb29saW5nIHdvdWxkIGJlIGZpbmUgaWYgd2UgY291bGQgZXN0aW1hdGUgJFlfe2l0fT1cYmV0YV8xWF97aXR9K1xiZXRhXzJaX2krZV97aXR9JA0KDQojIEZpeGVkIEVmZmVjdHMNCldpdGggVFNDUyBkYXRhIHRoYXQgY29udGFpbnMgdGltZS1jb25zdGFudCB1bml0LWxldmVsIG9taXR0ZWQgdmFyaWFibGUgYmlhcywgZml4ZWQgZWZmZWN0cyBjYW4gYmUgdXNlZCB0byBlc3RpbWF0ZSB0aGUgdW5iaWFzZWQgcmVsYXRpb25zaGlwLCBldmVuIGlmIHRoZSBvbWl0dGVkIHZhcmlhYmxlICRaJCBpcyBub3Qgb2JzZXJ2ZWQuDQoNCmBgYHtyfQ0KZmU8LXBsbShZflgsIGRpcnR5LCBpbmRleD1jKCJOIiwgIlRpbWUiKSwgbWV0aG9kPSJ3aXRoaW4iKQ0Kc3VtbWFyeShmZSkNCmBgYA0KDQpXaHkgZG9lcyB0aGlzIHdvcms/DQoNClRoZSBmaXhlZCBlZmZlY3QgZXN0aW1hdG9yIGNvbnNpZGVycyBvbmx5IHRoZSB3aXRoaW4tdW5pdCB2YXJpYXRpb24sIGFuZCByZW1vdmVzIHRoZSBiZXR3ZWVuIHVuaXQgdmFyaWF0aW9uLg0KDQpJbiBvdGhlciB3b3JkcywgdGhlIGRhdGEgYXJlIGdyb3VwIGRlbWVhbmVkLSBlYWNoIG9ic2VydmF0aW9uIGZvciBlYWNoICppKiBpcyBzdWJ0cmFjdGVkIGZyb20gdGhlIG1lYW4gZm9yIHRoYXQgdW5pdCBvdmVyIHRpbWUuDQoNCkJlY2F1c2UgdGhlIGVmZmVjdCBvZiAqWiogaXMgY29uc3RhbnQgb3ZlciB0aW1lLCBkZW1lYW5pbmcgcmVtb3ZlcyBpdHMgZWZmZWN0IGFuZCB0aGUgYmlhcyBpdCBpbnRyb2R1Y2VzDQoNCldlIGNhbiBkbyB0aGlzIG1hbnVhbGx5Og0KDQpgYGB7cn0NCmRlbWVhbjwtZGlydHkgJT4lDQogIGRwbHlyOjphcnJhbmdlKE4sVGltZSklPiUNCiAgZHBseXI6Omdyb3VwX2J5KE4pICU+JQ0KICBkcGx5cjo6bXV0YXRlKG1lYW5fWD1tZWFuKFgpLA0KICAgICAgICAgbWVhbl9ZPW1lYW4oWSksDQogICAgICAgICBkZW1lYW5fWD1YLW1lYW5fWCwNCiAgICAgICAgIGRlbWVhbl9ZPVktbWVhbl9ZKQ0KZGVtZWFuDQpmZV9tYW51YWw8LWxtKGRlbWVhbl9ZfmRlbWVhbl9YLTEsIGRhdGE9ZGVtZWFuKQ0Kc3VtbWFyeShmZV9tYW51YWwpDQoNCmRlbWVhbiAlPiUNCiAgZ2dwbG90KGFlcyh4PWRlbWVhbl9YLCB5PWRlbWVhbl9ZKSkrDQogIGdlb21fcG9pbnQoYWVzKGNvbG9yPWFzLmZhY3RvcihOKSkpKw0KICBnZW9tX3Ntb290aChtZXRob2Q9ImxtIiwgc2U9RikNCg0KYGBgDQoNClRoZSB3aXRoaW4gZXN0aW1hdG9yIGlzIHR5cGljYWxseSBpbnRyb2R1Y2VkIHdpdGggdGhlIGR1bW15IHZhcmlhYmxlIG5vdGF0aW9uIC0gd2hlcmUgTiBpbmRpY2F0b3JzIGZvciBlYWNoIHVuaXQgKG9yIE4tMSBhbmQgdGhlIGludGVyY2VwdCkuICBUaGVzZSBhcmUgZXF1aXZhbGVudCBpbiBPTFMgKG5vdCBpbiBHTE1zKS4gIE1vc3Qgc29mdHdhcmUgKHBsbSBpbiBSLCB4dHJlZywgZmUgaW4gU3RhdGEpIHVzZXMgdGhlIHdpdGhpbiB0cmFuc2Zvcm0gIA0KDQpgYGB7cn0NCmZlX2R1bW15IDwtDQogIGxtKFl+WCthcy5mYWN0b3IoTiktMSwgZGF0YT1kaXJ0eSkNCg0Kc3VtbWFyeShmZV9kdW1teSkNCnN1bW1hcnkoZmVfbWFudWFsKQ0Kc3VtbWFyeShmZSkNCmBgYA0KDQpOb3RlIHRoYXQgdGhlIHN0YW5kYXJkIGVycm9ycyBhcmUgc2xpZ2h0bHkgZGlmZmVyZW50IGJlY2F1c2UgdGhlIGRlbWVhbmVkIG1vZGVsIGRvZXNuJ3QgaGF2ZSB0aGUgcmlnaHQgZGVncmVlcyBvZiBmcmVlZG9tLiAgWW91IHNob3VsZCB1c2UgcGxtKCkgZm9yIHRoZSB3aXRoaW4gdHJhbnNmb3JtIGFzIGl0IGNvcnJlY3RzIGZvciB0aGlzLg0KDQojIyBJbnRlcnByZXRhdGlvbg0KSW50ZXJwcmV0YXRpb24gaXMgc3RhbmRhcmQsIGJ1dCB3aXRoIGEgY2F2ZWF0DQpgYGB7cn0NCnN1bW1hcnkoZmUpDQpzZChkaXJ0eSRYKQ0KY29lZihmZSkqc2QoZGlydHkkWCkNCg0Kc2QoZGVtZWFuJGRlbWVhbl9YKQ0KY29lZihmZSkqc2QoZGVtZWFuJGRlbWVhbl9YKQ0KYGBgDQoNClRha2Vhd2F5OiBDb2VmZmljaWVudHMgb24gTGluZWFyIEZFIHJlZ3Jlc3NvcnMgYXJlIGNvcnJlY3RseSBpbnRlcnByZXRlZCBhcyB0aGUgZWZmZWN0IG9mIGEgb25lIHVuaXQgaW5jcmVhc2UgaW4gKnRoZSB3aXRoaW4gdW5pdCogWC4gIFRoZSB3aXRoaW4gdW5pdCB2YXJpYW5jZSBpcyBhbHdheXMgbm8gbGFyZ2VyIHRoYW4gdGhlIHRvdGFsIHZhcmlhbmNlIGluIFggKG9mdGVuIHNpZ25pZmljYW50bHkgc21hbGxlciwgaGVyZSBhYm91dCAxLzIpLiAgQ2FsY3VsYXRlIHN1YnN0YW50aXZlIGVmZmVjdHMgdXNpbmcgd2l0aGluIFguIChAbXVtbW9sbzIwMThpbXByb3ZpbmcpDQoNCiMjIERyYXdiYWNrcw0KMS4gTm8gZXN0aW1hdGVzIGZvciB0aW1lLWludmFyaWFudCB2YXJpYWJsZXMNCg0KYGBge3J9DQp0aW1lX2ludjwtZGlydHkNCnRpbWVfaW52JEs8LWlmZWxzZShkaXJ0eSROPD0yLCAxLCAwKQ0KdGltZV9pbnYkWTwtMy0yKnRpbWVfaW52JFgrNCp0aW1lX2ludiRaLTMqdGltZV9pbnYkSytybm9ybShucm93KHRpbWVfaW52KSwwLCAuNSkNCg0KZHJvcF9tb2RlbDwtcGxtKFl+WCtLLCBtb2RlbD0id2l0aGluIiwgaW5kZXggPSBjKCJOIiwgIlRpbWUiKSwgZGF0YT10aW1lX2ludikNCnN1bW1hcnkoZHJvcF9tb2RlbCkNCg0KI1doeSBub3Q/IA0KdGltZV9pbnYgJT4lDQogIGdyb3VwX2J5KE4pICU+JQ0KICBtdXRhdGUodmFyX2s9Sy1tZWFuKEspKSAlPiUNCiAgdW5ncm91cCgpICU+JQ0KICBzZWxlY3QodmFyX2spICU+JQ0KICBzdW1tYXJ5KCkNCmBgYA0KDQpUaGUgRkUgZXN0aW1hdG9yIHN3ZWVwcyBvdXQgYWxsIHZhcmlhdGlvbiBvbiBLLCBiZWNhdXNlIEsgb25seSBoYXMgYmV0d2Vlbi11bml0IHZhcmlhbmNlLCBub3Qgd2l0aGluIHVuaXQgdmFyaWFuY2UuDQoNCjIuIExvc3Mgb2Ygb2JzZXJ2YXRpb25zIHdpdGhvdXQgdmFyaWF0aW9uIGluIHRoZSBEViBpbiBlaXRoZXIgY29uZGl0aW9uYWwgb3IgdW5jb25kaXRpb25hbCBsb2dpc3RpYyByZWdyZXNzaW9uLiANCmBgYHtyfQ0KZGF0YSAlPiUNCiAgZ3JvdXBfYnkoY2NvZGUpICU+JQ0KICBzdW1tYXJpemUodmFyX2RlbT12YXIobmEub21pdCh2ZGVtX2RlbSkpKQ0KDQpsb2dpdDwtY2xvZ2l0KHZkZW1fZGVtfkxNSUxFWCtzdHJhdGEoY2NvZGUpLCBkYXRhPWRhdGEpDQpzdW1tYXJ5KGxvZ2l0KQ0KDQpgYGANCkEgbG90IGhhcyBiZWVuIG1hZGUgb2YgdGhpcyBpc3N1ZSwgYnV0IGRvZXMgaXQgbWF0dGVyPyAoQGNvb2syMDIwZml4ZWQpDQoNCiJGZWVscyIgcHJvYmxlbWF0aWMgdGhhdCB0aGUgbW9kZWwgaWdub3JlcyBhIHBvcnRpb24gb2YgdGhlIGRhdGEuICBDYW4gYmUgc2V2ZXJlIGlmIHRoZSBldmVudCBpbiBxdWVzdGlvbiBpcyByYXJlL2NvbW1vbi4NCg0KQ29uY3JldGUgaXNzdWVzOg0KDQoxLiBObyBlc3RpbWF0ZXMgb2YgRkUsIHNvIG5vIGluZGl2aWR1YWwgTUVzIChzaW1pbGFyIHRvIENveCBQSCBtb2RlbCkuDQoNCjIuIEJpYXNlZCBlc3RpbWF0ZXMgb2YgYmFzZWxpbmUgcmF0ZSBvZiBldmVudCBiZWNhdXNlIG5vbi1ldmVudCB1bml0cyBhcmUgcmVtb3ZlZC4gQ29ycmVjdCBpbnRlcnByZXRhdGlvbiBpcyBiYXNlbGluZSByYXRlIGZvciB1bml0cyB0aGF0IGV4cGVyaWVuY2UgdGhlIGV2ZW50Lg0KDQojIyMgUGVuYWxpemVkIE1MIA0KQGNvb2syMDIwZml4ZWQgcmVjYXN0IHRoZSB1bmNvbmRpdGlvbmFsICh1bml0LWR1bW15KSBGRSBwcm9ibGVtIGFzIG9uZSBvZiAqc2VwYXJhdGlvbiouDQoNClNlcGFyYXRpb24gb2NjdXJzIHdoZW4gYSB2YXJpYWJsZSBwZXJmZWN0bHkgcHJlZGljdHMgdGhlIERWLSBoZXJlIHRoZSB1bml0IGRvZXMuIChJbWFnaW5lIGEgdGFibGUgb2YgWSBhbmQgTiwgaWYgb25lIG9yIG1vcmUgY2VsbHMgYXJlIGVtcHR5LCB0aGlzIGlzIHNlcGFyYXRpb24pDQoNCk1MIHNvbHV0aW9ucyAqZG8gbm90IGV4aXN0KiB1bmRlciBzZXBhcmF0aW9uLSB0aGUgTEwgaXMgZmxhdCBiZWNhdXNlIGZpdCBjYW4gYWx3YXlzIGJlIGltcHJvdmVkIGJ5IHB1c2hpbmcgdGhlIHNlcGFyYXRpbmcgY29lZmZpY2llbnQgbW9yZSB0b3dhcmRzIG5lZ2F0aXZlIChwb3NpdGl2ZSkgaW5maW5pdHkuDQoNCldlbGwga25vd24gc29sdXRpb24gaXMgdG8gcGVuYWxpemUgdGhlIG1heGltdW0gbGlrZWxpaG9vZCB0byBwdW5pc2ggbGFyZ2UgY29lZmZpY2llbnRzIChtYXkgYmUgZmFtaWxpYXIgYXMgcmlkZ2UvbGFzc28sIGJ1dCBzcGVjaWZpYyBwZW5hbHR5IGlzIGRpZmZlcmVudC4pDQoNCmBgYHtyfQ0KcGVuYWxpemVkX2ZlPC1nbG0odmRlbV9kZW1+TE1JTEVYK2FzLmZhY3RvcihjY29kZSksIGRhdGE9ZGF0YSwNCiAgICAgICAgICAgICAgICAgIGZhbWlsdHk9ImJpbm9taWFsIihsaW5rPSJsb2dpdCIpLCBtZXRob2Q9ImJyZ2xtRml0IikNCnN1bW1hcnkocGVuYWxpemVkX2ZlKQ0KYGBgDQpOb3RlIHRoYXQgdGhlIHVuY29uZGl0aW9uYWwgRkUgZXN0aW1hdG9yIGlzIGJpYXNlZCBkdWUgdG8gdGhlIGluY2lkZW50YWwgcGFyYW1ldGVycyBwcm9ibGVtLCB3aGljaCBjYW4gYmUgc2V2ZXJlIGluIHNtYWxsIFQuICBQZW5hbGl6aW5nIHRoZSBNTCBkb2VzIG5vdCBjaGFuZ2UgdGhpcy4gDQoNCkluY2lkZW50YWwgcGFyYW1ldGVycyBwcm9ibGVtIGlzIGp1c3QgYSBzcGVjaWFsIGNhc2Ugb2Ygd2VsbCBrbm93biBzbWFsbCBzYW1wbGUgYmlhcyBvZiBNTEUgKE1MRSBpcyBjb25zaXN0ZW50LCBub3QgdW5iaWFzZWQsIGFuZCBjb25zaXN0ZW5jeSByZWxpZXMgb24gYXN5bXB0b3RpY3MpLg0KDQpBcyBOIGdyb3dzIHdpdGhvdXQgVCwgdGhlIG51bWJlciBvZiAnaW5jaWRlbnRhbCBwYXJhbWV0ZXJzJyAodGhlIHVuaXQgZHVtbWllcykgZ3Jvd3MsIHNvIHdlIGFyZSB1c2luZyBUIHBlcmlvZHMgdG8gZXN0aW1hdGUgYSBncmVhdGVyIGFuZCBncmVhdGVyIG51bWJlciBvZiBwYXJhbWV0ZXJzLg0KDQojIFJhbmRvbSBFZmZlY3RzDQoNCldoYXQgaWYgJFokIGRvZXMgbm90IGNhdXNlICRYJD8NCg0KVGhlcmUncyBubyBPVkIgKHJlY2FsbCBuZWNlc3NhcnkgY29uZGl0aW9ucykNCg0KRkUgZXN0aW1hdG9yIGlzIHN0aWxsIHVuYmlhc2VkDQoNClBvb2xlZCBlc3RpbWF0b3IgdW5iaWFzZWQsIGJ1dCBpbmNvcnJlY3QgU0UvdC1zdGF0cyBiZWNhdXNlIHVuaXQgZWZmZWN0IGNyZWF0ZXMgc2VyaWFsIGNvcnJlbGF0aW9uIGluIGVycm9ycw0KDQoNCmBgYHtyfQ0KI01ha2Ugc29tZSBkYXRhIHRvIGJldHRlciBjb250cm9sIHRoZSByZWxhdGlvbnNoaXBzDQpOPC1zZXEoMSw1LDEpDQpUaW1lPC1zZXEoMSw1MCwxKQ0KcmFuZG9tPC1leHBhbmQuZ3JpZChOLCBUaW1lKQ0KbmFtZXMocmFuZG9tKTwtYygiTiIsICJUaW1lIikNCnJhbmRvbTwtIHJhbmRvbSAlPiUgDQogIGRwbHlyOjphcnJhbmdlKFRpbWUsIE4pDQoNCiNEcmF3IHRoZSB1bm9ic2VydmVkIGVmZmVjdCwgSVYsIERWLCBlcnJvcg0KWjwtcm5vcm0obGVuZ3RoKHVuaXF1ZShyYW5kb20kTikpLCAtMiwgLjUpDQpyYW5kb20kWjwtcmVwKFosIGxlbmd0aChUaW1lKSkNCnJhbmRvbSRYPC1ybm9ybShucm93KHJhbmRvbSksIDEsIC4yNSkNCnJhbmRvbSRZPC0zLTIqcmFuZG9tJFgrNCpyYW5kb20kWitybm9ybShucm93KHJhbmRvbSksMCwgLjUpDQoNCiNSdW4gdGhlIHBvb2xlZCBtb2RlbA0KcmFuZG9tX3Bvb2w8LWxtKFl+WCwgZGF0YT1yYW5kb20pDQpzdW1tYXJ5KHJhbmRvbV9wb29sKQ0KDQojUGxvdCB0aGUgcG9vbGVkIG1vZGVsIC0gd2hhdCBhcmUgd2UgbG9va2luZyBhdD8NCnJhbmRvbSAlPiUNCiAgZ2dwbG90KGFlcyh4PVgsIHk9WSkpKw0KICBnZW9tX3BvaW50KGFlcyhjb2xvcj1hcy5mYWN0b3IoTikpKSsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kPSJsbSIsIHNlPUYpDQoNCiNQbG90IHVuaXQgaW50ZXJjZXB0cy9zbG9wZXMNCnJhbmRvbSAlPiUNCiAgZ2dwbG90KGFlcyh4PVgsIHk9WSwgY29sb3I9YXMuZmFjdG9yKE4pKSkrDQogIGdlb21fcG9pbnQoKSsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kPSJsbSIsIHNlPUYpDQoNCiNSRSBlc3RpbWF0b3INCnJlPC1wbG0oWX5YLCByYW5kb20sIG1vZGVsID0gInJhbmRvbSIpDQpzdW1tYXJ5KHJlKQ0KDQpgYGANCg0KIyMgUG9vbGVkIG1vZGVsIGhhcyBpbmNvcnJlY3QgdmFyaWFuY2UNCmBgYHtyfQ0KI1RydWUgZXJyb3INCnJhbmRvbSRlcnJvciA8LXJhbmRvbSRZLSgzLTIqcmFuZG9tJFgrNCpyYW5kb20kWikNCg0KI0dldCBlc3RpbWF0ZWQgZXJyb3IgZnJvbSBwb29sZWQgbW9kZWwNCnJhbmRvbSRyZXNpZDwtcmVzaWQocmFuZG9tX3Bvb2wpDQoNCnJhbmRvbSAlPiUNCiAgZHBseXI6OnNlbGVjdChlcnJvciwgcmVzaWQpICU+JQ0KICBwaXZvdF9sb25nZXIoY29scyA9IGV2ZXJ5dGhpbmcoKSkgJT4lDQogIGdncGxvdCgpKw0KICBnZW9tX2hpc3RvZ3JhbShhZXModmFsdWUsIGZpbGw9bmFtZSwgYWxwaGE9LjIpKSsNCiAgZ3VpZGVzKGFscGhhPSJub25lIikNCg0KZV9yZXNpZCA9IHN1bSgocmFuZG9tJHJlc2lkKV4yKS8yNDgNCmVfZXJyb3IgPSBzdW0oKHJhbmRvbSRlcnJvcileMikvMjUwDQoNCmVfcmVzaWQNCmVfZXJyb3INCg0KIyBIb3cgZG9lcyB0aGlzIGFmZmVjdCBiZXRhIHNlIGFuZCB0LXN0YXRzPw0Kc3FydChlX3Jlc2lkIC8gc3VtKChyYW5kb20kWCAtIG1lYW4ocmFuZG9tJFgpKV4yKSkNCnNxcnQoZV9lcnJvciAvIHN1bSgocmFuZG9tJFggLSBtZWFuKHJhbmRvbSRYKSleMikpDQoNCnN1bW1hcnkocmFuZG9tX3Bvb2wpDQpzdW1tYXJ5KHJlKQ0KDQpgYGANCg0KV2UgY2FuIHNlZSB0aGF0IG91ciBTRXMgKGFuZCBieSBleHRlbnNpb24gdC1zdGF0cykgZm9yIHRoZSBwb29sZWQgbW9kZWwgYXJlIGluY29ycmVjdC4gIFRoaXMgaXMgYmVjdWFzZSBvdXIgZXN0aW1hdGUgb2YgJFxzaWdtYV4yJCAodmFyaWFuY2Ugb2YgdGhlIGVycm9yIHRlcm0pIGlzIHdyb25nIGJlY2F1c2UgdGhlIHBvb2xlZCBlc3RpbWF0b3IgaW5jbHVkZXMgdGhlIGVmZmVjdCBvZiAkWiQgb24gJFkkIGluIHRoZSB2YXJpYW5jZS4NCg0KUmFuZG9tIGVmZmVjdHMgcHVyZ2UgdGhlIHZhcmlhbmNlIGNvbnRyaWJ1dGVkIGJ5ICRaJCBhbmQgdGhlcmVmb3JlIHJldHVybiBTRSB0aGF0IG1hdGNoIFNFIGNhbGN1bGF0ZWQgd2l0aCB0aGUga25vd24gZXJyb3IgdGVybS4NCg0KIyMjIEF1dG9jb3JyZWxhdGlvbiByb2J1c3Qgc3RhbmRhcmQgZXJyb3JzDQpTaW5jZSB0aGUgcG9vbGVkIG1vZGVsIGlzIHVuYmlhc2VkLCB3ZSBjYW4gc2ltcGx5IGNvcnJlY3QgdGhlIHN0YW5kYXJkIGVycm9yIGVzaXRtYXRlcy4gIEhlcmUgdXNpbmcgY2x1c3Rlci1yb2J1c3QgU0UuDQoNCkhvd2V2ZXIsIGNsdXN0ZXItcm9idXN0IFNFIGFyZSAqYXN5bXB0b3RpY2FsbHkqIGNvcnJlY3QgKGluIHRoZSBudW1iZXIgb2YgdW5pdHMgJE4kICpub3QqIHRoZSBudW1iZXIgb2Ygb2JzZXJ2YXRpb25zKS4gT3VyICpOKiBpcyA1LCB3aGljaCBpcy4uLm5vdCBhc3ltcHRvdGljLg0KYGBge3J9DQoNCmNvZWZ0ZXN0KHJhbmRvbV9wb29sLCB2Y292PXZjb3ZIQyhyYW5kb21fcG9vbCwgdHlwZSA9ICJIQzAiLCBncm91cD0iTiIpKQ0KDQpgYGAgDQoNClRoZXNlIGxvb2sgdmVyeSBzaW1pbGFyIHRvIG91ciB1bmNvcnJlY3RlZCBTRXMuDQoNCk1ha2UgdGhlIGRhdGEgYmlnZ2VyLg0KDQpgYGB7cn0NCiNNYWtlIHNvbWUgZGF0YSB0byBiZXR0ZXIgY29udHJvbCB0aGUgcmVsYXRpb25zaGlwcw0KTl9sYXJnZTwtc2VxKDEsNTAwMCwxKQ0KVGltZTwtc2VxKDEsNTAsMSkNCnJhbmRvbV9sYXJnZTwtZXhwYW5kLmdyaWQoTl9sYXJnZSwgVGltZSkNCm5hbWVzKHJhbmRvbV9sYXJnZSk8LWMoIk4iLCAiVGltZSIpDQpyYW5kb21fbGFyZ2U8LSByYW5kb21fbGFyZ2UgJT4lIA0KICBkcGx5cjo6YXJyYW5nZShUaW1lLCBOKQ0KDQojRHJhdyB0aGUgdW5vYnNlcnZlZCBlZmZlY3QsIElWLCBEViwgZXJyb3INClpfbGFyZ2U8LXJub3JtKGxlbmd0aCh1bmlxdWUocmFuZG9tX2xhcmdlJE4pKSwgLTIsIC41KQ0KcmFuZG9tX2xhcmdlJFo8LXJlcChaX2xhcmdlLCBsZW5ndGgoVGltZSkpDQpyYW5kb21fbGFyZ2UkWDwtcm5vcm0obnJvdyhyYW5kb21fbGFyZ2UpLCAxLCAuMjUpDQpyYW5kb21fbGFyZ2UkWTwtMy0yKnJhbmRvbV9sYXJnZSRYKzQqcmFuZG9tX2xhcmdlJForcm5vcm0obnJvdyhyYW5kb21fbGFyZ2UpLDAsIC41KQ0KDQojUnVuIHRoZSBwb29sZWQgbW9kZWwNCnJhbmRvbV9wb29sX2xhcmdlPC1sbShZflgsIGRhdGE9cmFuZG9tX2xhcmdlKQ0Kc3VtbWFyeShyYW5kb21fcG9vbF9sYXJnZSwgY2x1c3Rlcj0iTiIpDQoNCmxhcmdlX2VfZXJyb3IgPC0gc3VtKChyYW5kb21fbGFyZ2UkWSAtKDIqcmFuZG9tX2xhcmdlJFgrNCpyYW5kb21fbGFyZ2UkWikpXjIpLyhsZW5ndGgoTl9sYXJnZSkpDQpzcXJ0KGxhcmdlX2VfZXJyb3IgLyBzdW0oKHJhbmRvbV9sYXJnZSRYIC0gbWVhbihyYW5kb21fbGFyZ2UkWCkpXjIpKQ0KDQpgYGANCiMjIFRlc3RpbmcgdGhlIHZhbGlkaXR5IG9mIHRoZSBSRSBhc3N1bXB0aW9uDQoNCkluIG9yZGVyIHRvIGJlIHVuYmlhc2VkLCB0aGUgUmFuZG9tIEVmZmVjdHMgZXN0aW1hdG9yIHJlcXVpcmVzIHRoYXQgdGhlcmUgaXMgbm8gY29ycmVsYXRpb24gYmV0d2VlbiB0aGUgdW5pdCBlZmZlY3RzIGFuZCB0aGUgZXhwbGFuYXRvcnkgdmFyaWFibGVzLg0KDQpUaGlzIGFzc3VtcHRpb24gaXMgdHlwaWNhbGx5IHRlc3RlZCB3aXRoIGEgSGF1c21hbiB0ZXN0IGNvbXBhcmluZyBhbiBGRSBhbmQgUkUgbW9kZWwgd2l0aCB0aGUgc2FtZSBzcGVjaWZpY2F0aW9uDQoNCmBgYHtyfQ0KI0ZpdCBhIEZFIG1vZGVsIHRvIHRoZSBzYW1lIGRhdGENCmZlPC1wbG0oWX5YLCByYW5kb20sIG1vZGVsID0gIndpdGhpbiIpDQoNCiNIYXVzbWFuIFRlc3QNCnBodGVzdChmZSwgcmUpDQoNCiNOb3RlLCBvcmRlciBvZiB0aGUgYXJndW1lbnRzIGRvZXMgbm90IG1hdHRlcg0KDQojQ2FuIGFsc28gY2FsY3VsYXRlIHRoZSBIYXVzbWFuIHN0YXRpc3RpYyBieSBoYW5kDQp0KGNvZWYoZmUpIC0gY29lZihyZSlbMl0pJSolIHNvbHZlKHZjb3YoZmUpLXZjb3YocmUpWzIsMl0pICUqJSAoY29lZihmZSktY29lZihyZSlbMl0pDQoNCg0KYGBgDQoNClRoZSBudWxsIGh5cG90aGVzaXMgb2YgdGhlIEhhdXNtYW4gdGVzdCBpcyAocm91Z2hseSkgdGhhdCB0aGUgY29lZmZpY2llbnQgdmVjdG9ycyBhcmUgZXF1YWwgaW4gYm90aCB0aGUgRkUgYW5kIFJFIG1vZGVscy4gIFJlamVjdGlvbiBpbmRpY2F0ZXMgdGhlIHR3byB2ZWN0b3JzIGFyZSBzdGF0aXN0aWNhbGx5IGRpZmZlcmVudC4gIFJlamVjdGlvbiBpcyB0eXBpY2FsbHkgdGFrZW4gdG8gc3VnZ2VzdCB2aW9sYXRpb24gb2YgdGhlIFJFIGFzc3VtcHRpb24uDQoNClJlY2FsbCB0aGF0IGJvdGggdGhlIEZFIGFuZCBSRSBtb2RlbHMgYXJlIHVuYmlhc2VkIHVuZGVyIHRoZSBSRSBhc3N1bXB0aW9ucyAodGhlIGZvcm1lciBpcyBub3QgZWZmaWNpZW50KS4gIFRodXMsIGlmIHRoZSBSRSBhc3N1bXB0aW9ucyBob2xkLCB3ZSB3b3VsZCBub3QgZXhwZWN0IGEgZGlmZmVyZW5jZS4gIEluIGNvbnRyYXN0LCBpZiB0aGUgUkUgYXNzdW1wdGlvbiByZWdhcmRpbmcgdGhlIGNvcnJlbGF0aW9uIG9mIHRoZSBpbmRpdmlkdWFsIGVmZmVjdHMgd2l0aCB0aGUgaW5kZXBlbmRlbnQgdmFyaWFibGVzIGlzIHZpb2xhdGVkLCBvbmx5IHRoZSBGRSBlc3RpbWF0b3IgaXMgdW5iaWFzZWQgYW5kIHRoZSBSRSBlc3RpbWF0b3IgaXMgYmlhc2VkLiAgVGhlcmVmb3JlLCB3ZSB3b3VsZCBleHBlY3QgZGlmZmVyZW5jZXMgaW4gdGhlIGVzdGltYXRlcy4NCg0KIyBUaGUgV2l0aGluLUJldHdlZW4gTW9kZWwNClJhdGhlciB0aGFuIGNob29zaW5nIGJldHdlZW4gZml4ZWQgYW5kIHJhbmRvbSBlZmZlY3RzLCB3ZSBjYW4gZXN0aW1hdGUgYSBjb21wb3VuZCBtb2RlbC4NCg0KUmVjYWxsIHRoYXQgdGhlIGdvYWwgb2YgYm90aCB0aGUgRkUgYW5kIFJFIG1vZGVscyBpcyB0byBhY2NvdW50IGZvciB1bml0LWxldmVsIGhldGVyb2dlbmVpdHkuICBUaGUgZnVuZGFtZW50YWwgZGlmZmVyZW5jZSBpcyB0aGF0IHRoZSBSRSBtb2RlbCByZXF1aXJlcyBubyBjb3ZhcmlhbmNlIGJldHdlZW4gdGhlIHVuaXQgZWZmZWN0cyBhbmQgdGhlIGVycm9yLiAgVGhlIEZFIG1vZGVsIGlzIGFnbm9zdGljIG9uIHRoaXMgYmVjYXVzZSBpdCBlbGltaW5hdGVzIGFsbCB2YXJpYXRpb24gb24gYWxsIHZhcmlhYmxlcyBkdWUgdG8gdW5pdCBlZmZlY3RzIHZpYSB0aGUgd2l0aGluIHRyYW5zZm9ybSAoc3VidHJhY3RpbmcgdGhlIHVuaXQgbWVhbnMgZnJvbSBlYWNoIHJlYWxpemF0aW9uIG9mICRZJCwgJFgkKQ0KDQpUaGUgcmlzayBvZiB0aGUgUkUgbW9kZWwsIHRoZW4sIGNhbiBiZSB0aG91Z2h0IG9mIGFzIGNvcnJlbGF0aW9uIGJldHdlZW4gdGhlc2UgdW5pdCBtZWFucyBhbmQgdGhlIGVycm9yIHRlcm0uICBBcyB3aXRoIHN0YW5kYXJkIE9WQiwgcHV0dGluZyB0aGUgdW5pdCBtZWFucyBpbnRvIHRoZSBlcXVhdGlvbiB3aWxsIHJlbW92ZSB0aGUgYmlhcyBhbmQgYWxsb3cgdGhlIFJFIGVzdGltYXRvciB0byByZWNvdmVyIHRoZSB1bmJpYXNlZCBjb2VmZmljaWVudHMgb24gJFgkLg0KDQpUaGUgdHJhZGl0aW9uYWwgYXBwcm9hY2ggY29tZXMgZnJvbSBAbXVuZGxhazE5Nzhwb29saW5nIGFuZCBpbnZvbHZlcyBlc3RpbWF0aW5nIHRoZSBmb2xsb3dpbmcgZXF1YXRpb24gd2l0aCB0aGUgUkUgZXN0aW1hdG9yOg0KDQokWV97aXR9PVxiZXRhXzFYX3tpdH0rXGJldGFfMlxvdmVybGluZXtYX2l9K2Vfe2l0fSQNCg0KV2hlcmUgJFxvdmVybGluZXtYX2l9JCBpcyB0aGUgdW5pdCBsZXZlbCBtZWFuIG9mICRYJA0KDQpBbHRlcm5hdGl2ZWx5LCB0aGUgdGltZS1zcGVjaWZpYyByZWFsaXphdGlvbnMgb2YgJFgkIGNhbiBiZSB3aXRoaW4tdHJhbnNmb3JtZWQgcHJpb3IgdG8gZXN0aW1hdGlvbi4NCg0KJFlfe2l0fT1cYmV0YV8xKFhfe2l0fS1cb3ZlcmxpbmV7WF9pfSkrXGJldGFfMlxvdmVybGluZXtYX2l9K2Vfe2l0fSQNCg0KDQpUaGUgc3BlY2lmaWMgbW9kZWwgeW91IHNob3VsZCB1c2UgZGVwZW5kcyBvbiB3aGljaCBjb2VmZmljaWVudHMgYXJlIG1vcmUgb2YgaW50ZXJlc3Q6IHRoZSBpbmRpdmlkdWFsIG9yIGFnZ3JlZ2F0ZS4gIFRoZSBmb3JtZXIgKE11bmRsYWspIHNwZWNpZmljYXRpb24gZmFjaWxpdGF0ZXMgaW50ZXJwcmV0YXRpb24gb2YgdGhlIGFnZ3JlZ2F0ZSAoZ3JvdXAgbWVhbikgdmFyaWFibGUuDQoNClRoZSBncm91cCBkZW1lYW5pbmcgaW4gdGhlIGxhdHRlciBhcHByb2FjaCBlbnN1cmVzIHRoYXQgdGhlIGluZGl2aWR1YWwgcmVhbGl6YXRpb25zIGFyZSB1bmNvcnJlbGF0ZWQgd2l0aCB0aGUgZ3JvdXAtbGV2ZWwgbWVhbi4gIEFzIGEgcmVzdWx0LCB0aGUgZ3JvdXAtbGV2ZWwgdGVybSBjYW5ub3QgYmUgaW50ZXJwcmV0ZWQsIGJlY2F1c2UgaXQgZG9lcyBub3QgY29udHJvbCBmb3IgdGhlIGVmZmVjdCBvZiB0aGUgaW5kaXZpZHVhbCByZWFsaXphdGlvbnMuDQoNCmBgYHtyfQ0KI1dlJ2xsIGZpdCB0aGUgc2Vjb25kIGVxdWF0aW9uIHRvIG91ciBSRSBkYXRhDQoNCiNGaXJzdCwgd2UgaGF2ZSB0byBncm91cCBkZW1lYW4NCmRlbWVhbl9yYW5kb208LXJhbmRvbSAlPiUNCiAgZHBseXI6OmFycmFuZ2UoTixUaW1lKSU+JQ0KICBncm91cF9ieShOKSAlPiUNCiAgbXV0YXRlKG1lYW5fWD1tZWFuKFgpLA0KICAgICAgICAgZGVtZWFuX1g9WC1tZWFuX1gpDQoNCiMgTm93IGluY2x1ZGUgYm90aCBYIHRlcm1zIGluIHRoZSBSRSBtb2RlbA0KcmVidzwtcGxtKFl+ZGVtZWFuX1ggKyBtZWFuX1gsIGRlbWVhbl9yYW5kb20sIG1vZGVsID0gInJhbmRvbSIpDQoNCmNvZWYocmVidykNCmNvZWYoZmUpDQpgYGANCk5vdGljZSB0aGF0IHRoZSBjb2VmZmljaWVudCBvbiB0aGUgd2l0aGluIGVmZmVjdCBmcm9tIHRoZSBSRUJXIG1vZGVsIGlzIHRoZSBzYW1lIGFzIHRoZSBGRSBlc3RpbWF0ZS4NCg0KV2UgY2FuIGFsc28gZXN0aW1hdGUgdGhlIE11bmRsYWsgdmVyc2lvbg0KYGBge3J9DQojTXVuZGxhayBmb3JtdWxhdGlvbg0KbXVuZGxhazwtcGxtKFl+WCArIG1lYW5fWCwgZGVtZWFuX3JhbmRvbSwgbW9kZWwgPSAicmFuZG9tIikNCmNvZWYobXVuZGxhaykNCg0KYGBgDQoNCkFnYWluLCB3ZSd2ZSBzdWNjZXNzZnVsbHkgcHVyZ2VkIHRoZSBjb2VmZmljaWVudHMgb24gdGhlIGluZGl2aWR1YWwgcmVhbGl6YXRpb25zIG9mICRYJC4gIE91ciBjb2VmZmljaWVudCBvbiAkXG92ZXJsaW5le1h9JCBoYXMgY2hhbmdlZC4gIFRoZSBSRVdCIGVzdGltYXRlIHdhcyAtNTYgd2hpY2ggd2UgY2FuIHNlZSBoZXJlIGlzIGFjdHVhbGx5IHRoZSBzdW0gb2YgdGhlIGJldHdlZW4gYW5kIHdpdGhpbiBjb2VmZmljaWVudHMgZnJvbSB0aGUgTXVuZGxhayBlc3RpbWF0b3Igb2YgLTU0IGFuZCAtMg0KDQojIER5bmFtaWMgTW9kZWxzDQoNCmBgYHtyfQ0KDQojQ2hlY2sgaG93IG91ciBkYXRhIGxvb2sNCmRhdGEgJT4lDQogIGRwbHlyOjpzZWxlY3QoYyhjY29kZSwgeWVhciwgTE1JTEVYLCB2MnhfcG9seWFyY2h5KSkgJT4lDQogIGZpbHRlcihjY29kZTwxMDApICU+JQ0KICBwaXZvdF9sb25nZXIoY29scyA9IGMoTE1JTEVYLCB2MnhfcG9seWFyY2h5KSwgdmFsdWVzX3RvID0gInZhbHVlcyIpJT4lDQogIGdncGxvdChhZXMoeT12YWx1ZXMsIHg9eWVhciwgY29sb3I9YXMuZmFjdG9yKGNjb2RlKSkpKw0KICBnZW9tX2xpbmUoKSsNCiAgZmFjZXRfd3JhcCh+bmFtZSwgc2NhbGVzPSJmcmVlX3kiKQ0KYGBgDQoNCiMjIFBhbmVsIFVuaXQgUm9vdCBUZXN0aW5nDQoNClBhbmVsIHVuaXQgcm9vdCB0ZXN0aW5nIGlzIGRpZmZpY3VsdCBhbmQgUiBpbXBsZW1lbnRhdGlvbnMgYXJlIHNvbWV3aGF0IGJhc2ljDQoNCldlIGNhbiBwZXJmb3JtIG91ciBvd24gdGVzdCB2aWEgdGhlIHAtdmFsdWUgYWdncmVnYXRpb24gbWV0aG9kIG9mIEBjaG9pMjAwMXVuaXQNCg0KV2UgcGVyZm9ybSBhbiBhdWdtZW50ZWQgRGlja2V5LUZ1bGxlciB0ZXN0IG9uIGVhY2ggcGFuZWwsIGFnZ3JlZ2F0ZSB0aGUgcC12YWx1ZXMNCg0KU3BlY2lmaWMgYWdncmVnYXRpb24gaXMgJC0yXHN1bV97bn1ee059IGxuKHBfbikkDQoNClRlc3Qgc3RhdGlzdGljIGlzIGRpc3RyaWJ1dGVkICRcY2hpXjIoMk4pJA0KDQpOIGhlcmUgaW5kaWNhdGVzIG51bWJlciBvZiBwYW5lbHMNCg0KV2UncmUgZ29pbmcgdG8gbG9vcCBvdmVyIHRoZSBwYW5lbHMsIHBlcmZvcm0gdGhlIHRlc3QsIHN0b3JlIHRoZSByZXN1bHRzDQoNCihZb3UgY291bGQgYWxzbyBkbyB0aGlzIGFzIGEgdmVjdG9yaXplZCBmdW5jdGlvbi4uLikNCg0KYGBge3IsIHdhcm5pbmc9RiwgbWVzc2FnZT1GfQ0KcHZhbHMgPC0gTlVMTA0KZm9yIChpIGluIHVuaXF1ZShkYXRhJGNjb2RlKSl7DQogIHRyeShkZnVsbGVyIDwtIGFkZi50ZXN0KGRhdGFbZGF0YSRjY29kZT09aSwgIkxNSUxFWCJdLCBrID0gMSkpDQogIHB2YWxzPC1yYmluZChwdmFscywgZGZ1bGxlciRwLnZhbHVlKQ0KfQ0KDQpoZWFkKHB2YWxzKQ0KDQojQ2hvaSdzIFAtdmFsdWUNCnRlc3Rfc3RhdDwtIC0yKnN1bShsb2cobmEub21pdChwdmFscykpKQ0KdGVzdF9zdGF0IA0KDQojVGhhdCdzIGdvaW5nIHRvIHJlamVjdCwgYnV0IGxldCdzIGdldCBhIHAtdmFsdWUgZm9yIGNvbXBsZXRlbmVzcw0KI1Rlc3QgaXMgZGlzdHJpYnV0ZWQgY2hpMigyTikgd2hlcmUgTiBpcyBwYW5lbHMNCg0Kcm91bmQocGNoaXNxKHRlc3Rfc3RhdCwgZGY9Mipucm93KG5hLm9taXQocHZhbHMpKSwgbG93ZXIudGFpbCA9IEYpLCBkaWdpdHM9MykNCmBgYA0KSW4gdGhlIHAtdmFsdWUgYWdncmVnYXRpb24gY2hhc2UsIHdlIGFyZSB0ZXN0aW5nIGEgc3BlY2lmaWMgbnVsbCBoeXBvdGhlc2lzIHRoYXQgYWxsIHRoZSBwYW5lbHMgaGF2ZSBhIHVuaXQgcm9vdCBhZ2FpbnN0IHRoZSBhbHRlcm5hdGl2ZSB0aGF0IGF0IGxlYXN0IG9uZSBpcyBzdGF0aW9uYXJ5Lg0KDQpUaGF0IG1pZ2h0IG5vdCBiZSB0aGUgbW9zdCByZWFzc3VyaW5nIHJlamVjdGlvbjsgb3RoZXIgdGVzdHMgaGF2ZSBkaWZmZXJlbnQgbnVsbHMuDQoNCiMjIEZpcnN0IERpZmZlcmVuY2luZw0KDQpUaGUgcGFuZWwgQURGIGRpZG4ndCBpbmRpY2F0ZSBhIG5lZWQgZm9yIGRpZmZlcmVuY2luZywgYnV0IGxldCdzIHRvIGlsbHVzdHJhdGUuDQoNCihVc3VhbCBjYXZlYXRzIGhlcmU7IGZpcnN0IGRpZmZlcmVuY2luZyBpcyBvbmx5IGFwcHJvcHJpYXRlIGZvciBJKDEpIHNlcmllcywgeW91IG5lZWQgdG8gdGVzdCB0aGUgZGlmZmVyZW5jZWQgc2VyaWVzIGZvciBzdGF0aW9uYXJpdHksIGV0Yy4pDQoNCg0KYGBge3J9DQojRGlmZmVyZW5jZSB0aGVzZSBvdXQgdG8gYmUgc2FmZQ0KZmQ8LXBkYXRhLmZyYW1lKGRhdGEsIGluZGV4ID0gYygiY2NvZGUiLCAieWVhciIpKQ0KZmQkZF9sbWlsZXg9ZGlmZihmZCRMTUlMRVgpDQpmZCRkX3BvbHlhcmNoeT1kaWZmKGZkJHYyeF9wb2x5YXJjaHkpDQoNCmZkICU+JQ0KICBkcGx5cjo6c2VsZWN0KGMoY2NvZGUsIHllYXIsIGRfbG1pbGV4LCBkX3BvbHlhcmNoeSkpICU+JQ0KICBmaWx0ZXIoY2NvZGUgJWluJSBzZXEoMiw5OSwxKSkgJT4lDQogIHBpdm90X2xvbmdlcihjb2xzID0gYyhkX2xtaWxleCwgZF9wb2x5YXJjaHkpLCB2YWx1ZXNfdG8gPSAidmFsdWVzIiklPiUNCiAgZ2dwbG90KGFlcyh5PXZhbHVlcywgeD15ZWFyLCBjb2xvcj1hcy5mYWN0b3IoY2NvZGUpKSkrDQogIGdlb21fcG9pbnQoKSsNCiAgZmFjZXRfd3JhcCh+bmFtZSwgc2NhbGVzPSJmcmVlX3kiKQ0KYGBgDQoNCiMjIFN0YXRpYw0KDQpNb3JlIGRldGFpbHMgaW4gQGRlMjAwOHRha2luZw0KDQpgYGB7cn0NCnN0YXRpYzwtbG0oZF9sbWlsZXh+ZF9wb2x5YXJjaHksIGRhdGE9ZmQpDQpzdW1tYXJ5KHN0YXRpYykNCg0KI0lsbHVzdHJhdGUgdGhlIGltcGFjdCBvZiAxIFNEIGNoYW5nZSBpbiBwb2x5YXJjaHkgKHRlbXBvcmFyeSkNCnRpbWU8LXNlcSgxLDEwLDEpDQpkZW08LWMocmVwKDAsMiksIA0KICAgICAgIHNkKG5hLm9taXQoZmQkZF9wb2x5YXJjaHkpKSwNCiAgICAgICByZXAoMCwgNykpDQpwcmVkX2RhdDwtY2JpbmQuZGF0YS5mcmFtZSh0aW1lLGRlbSkNCnByZWRfZGF0JG1pbGV4X2hhdDwtcHJlZF9kYXQkZGVtKmNvZWYoc3RhdGljKVsyXQ0KcHJlZF9kYXQgJT4lDQogIGdncGxvdChhZXMoeD10aW1lLCB5PW1pbGV4X2hhdCkpKw0KICBnZW9tX2xpbmUoKQ0KYGBgDQpJZiB0aGUgcmVncmVzc2lvbiBlcXVhdGlvbiBpcyAkWV90PVxiZXRhXzArXGJldGFfMVhfdCtcZXBzaWxvbl90JA0KDQpUaGUgZWZmZWN0IG9mICRYX3QkIG9uICRZX3QkIGlzICRcZnJhY3tcZGVsdGEgWV90fXtcZGVsdGEgWF90fSQgd2hpY2ggaXMgJFxiZXRhXzEkDQoNCk1vdmluZyBmb3J3YXJkIG9uZSBwZXJpb2Q6ICRZX3t0KzF9PVxiZXRhXzArXGJldGFfMVhfe3QrMX0rXGVwc2lsb25fe3QrMX0kDQoNClRoZSBkZXJpdmF0aXZlIG9mIHRoYXQgcmVncmVzc2lvbiB3aXRoIHJlc3BlY3QgdG8gJFhfdCQgaXMgemVyby4gDQoNCiMjIEZpbml0ZSBMYWcNCmBgYHtyfQ0KZmQkbGFnX3BvbHlhcmNoeT1sYWcoZmQkZF9wb2x5YXJjaHkpDQpmZCRsYWdfbG1pbGV4PWxhZyhmZCRkX2xtaWxleCkNCg0KbGFnMTwtbG0oZF9sbWlsZXh+ZF9wb2x5YXJjaHkrbGFnX3BvbHlhcmNoeSwgZGF0YT1mZCkNCnN1bW1hcnkobGFnMSkNCg0KcHJlZF9kYXQ8LXByZWRfZGF0ICU+JSANCiAgbXV0YXRlKGxhZ19kZW09ZHBseXI6OmxhZyhkZW0pKQ0KcHJlZF9kYXQkbWlsZXhfaGF0PC1wcmVkX2RhdCRkZW0qY29lZihsYWcxKVsyXStwcmVkX2RhdCRsYWdfZGVtKmNvZWYobGFnMSlbM10NCnByZWRfZGF0ICU+JQ0KICBnZ3Bsb3QoYWVzKHg9dGltZSwgeT1taWxleF9oYXQpKSsNCiAgZ2VvbV9saW5lKCkNCmBgYA0KDQpJZiB0aGUgcmVncmVzc2lvbiBlcXVhdGlvbiBpcyAkWV90PVxiZXRhXzArXGJldGFfMVhfdCtcYmV0YV8yWF97dC0xfStcZXBzaWxvbl90JA0KDQpUaGUgZWZmZWN0IG9mICRYX3QkIG9uICRZX3QkIGlzICRcZnJhY3tcZGVsdGF9e1xkZWx0YSBYfSBcYmV0YV8wK1xiZXRhXzFYX3QrXGJldGFfMlhfe3QtMX0rXGVwc2lsb25fdCQgd2hpY2ggaXMgJFxiZXRhXzEkDQoNCk1vdmluZyBmb3J3YXJkIG9uZSBwZXJpb2Q6ICRZX3t0KzF9PVxiZXRhXzArXGJldGFfMVhfe3QrMX0rXGJldGFfMlhfdCtcZXBzaWxvbl97dCsxfSQNCg0KVGhlIGRlcml2YXRpdmUgb2YgdGhhdCByZWdyZXNzaW9uIHdpdGggcmVzcGVjdCB0byAkWF90JCBpcyAkXGJldGFfMiQNCg0KRGVyaXZhdGl2ZSBpbiBwZXJpb2RzIGJleW9uZCAkdCsxJCBpcyB6ZXJvIGFzIGJlZm9yZS4NCg0KIyMgTGFnZ2VkIERlcGVuZGVudCBWYXJpYWJsZSBNb2RlbHMNCg0KYGBge3J9DQpsZHY8LWxtKGRfbG1pbGV4fmxhZ19sbWlsZXgrZF9wb2x5YXJjaHksIGRhdGE9ZmQpDQpzdW1tYXJ5KGxkdikNCg0KcHJlZF9kYXRbMTozLF0kbWlsZXhfaGF0PC1jb2VmKGxkdilbM10qcHJlZF9kYXRbMTozLF0kZGVtDQpwcmVkX2RhdFs0OjEwLF0kbWlsZXhfaGF0PC1jb2VmKGxkdilbMl1eKHByZWRfZGF0WzQ6MTAsXSR0aW1lLTMpKmNvZWYobGR2KVszXSpwcmVkX2RhdFszLCJkZW0iXQ0KcHJlZF9kYXQgJT4lDQogIGdncGxvdChhZXMoeD10aW1lLCB5PW1pbGV4X2hhdCkpKw0KICBnZW9tX2xpbmUoKQ0KDQojV2hhdCBhYm91dCBhIHBlcm1hbmVudCBzaGlmdD8NCmNvZWYobGR2KQ0KbHJtPC1jb2VmKGxkdilbM10qc2QobmEub21pdChmZCRkX3BvbHlhcmNoeSkpLygxLWNvZWYobGR2KVsyXSkNCmxybQ0KYGBgDQoNCkluIHRoZSBjYXNlIG9mIGEgdGVtcG9yYXJ5IHNob2NrIHRvIFgsIHRoZSBlZmZlY3QgZGVjYXlzIGdlb21ldHJpY2FsbHkgYnkgYXNzdW1wdGlvbiAoZS5nLiwgZm9yY2VkIGJ5IHRoZSBhc3N1bXB0aW9uIG9mIHRoZSBtb2RlbCkNCg0KVG8gc2VlIHRoYXQsIGxldCdzIGNvbnNpZGVyIHRoZSBlZmZlY3Qgb2YgJFhfdCQgYXQgdGltZSAkdCsxJCBhbmQgJHQrMiQNCg0KVGhlIGdlbmVyYWwgZXF1YXRpb24gJFlfe3R9PVxiZXRhXzArXGFscGhhIFlfe3QtMX0rXGJldGFfMVhfe3R9K1xlcHNpbG9uX3t0fSQNCg0KQXQgJHQrMSQgd2UgaGF2ZQ0KDQokWV97dCsxfT1cYmV0YV8wK1xhbHBoYSBZX3t0fStcYmV0YV8xWF97dCsxfStcZXBzaWxvbl97dCsxfSQNCg0KU3Vic3RpdHV0ZSBmb3IgJFlfdCQgLSBkcm9wIG91dCB0aGUgZXJyb3IgdGVybXMsIGNvbnN0YW50IGZvciBlYXNlDQoNCiRZX3t0KzF9PVxhbHBoYShcYWxwaGEgWV97dC0xfStcYmV0YV8xWF97dH0pK1xiZXRhXzFYX3t0KzF9JA0KDQpGaXJzdCBkZXJpdmF0aXZlIHdpdGggcmVzcGVjdCB0byAkWF90JCBpcyAkXGFscGhhXHRpbWVzXGJldGFfMSQNCg0KVGhpcyBtYWtlcyBpbnR1aXRpdmUgc2Vuc2UgLSAkWF90JCBhZmZlY3RzICRZX3QkIGJ5ICRcYmV0YV8xJC4gIEluIHR1cm4sICRZX3QkIGFmZmVjdHMgJFlfe3QrMX0kIGJ5ICRcYWxwaGEkLCB0aGUgZXh0ZW50IHRvIHdoaWNoICRZJCBpcyBzZXJpYWxseSBjb3JyZWxhdGVkLiANCg0KU2ltaWxhcmx5IGF0ICR0KzIkDQoNCiRZX3t0KzJ9PVxiZXRhXzArXGFscGhhIFlfe3QrMX0rXGJldGFfMVhfe3QrMn0rXGVwc2lsb25fe3QrMn0kDQoNClN1YnN0aXR1dGUgZm9yICRZX3t0KzF9JA0KDQokWV97dCsyfT1cYmV0YV8wK1xhbHBoYSAoXGFscGhhIFlfe3R9K1xiZXRhXzFYX3t0KzF9KStcYmV0YV8xWF97dCsyfStcZXBzaWxvbl97dCsyfSQNCg0KQW5kIGFnYWluIGZvciAkWV97dH0kDQoNCiRZX3t0KzJ9PVxiZXRhXzArXGFscGhhIFtcYWxwaGEoXGFscGhhIFlfe3QtMX0rXGJldGFfMVhfe3R9KStcYmV0YV8xWF97dCsxfV0rXGJldGFfMVhfe3QrMn0rXGVwc2lsb25fe3QrMn0kDQoNClRoaXMgaXMga2luZCBvZiB1Z2x5LCBidXQgYW55dGhpbmcgdGhhdCdzIG5vdCBtdWx0aXBsaWVkIGJ5ICRYX3QkIGNhbiBnbyBhd2F5LCB3aGljaCBpcyBiYXNpY2FsbHkgZXZlcnl0aGluZw0KDQpXZSdyZSBsZWZ0IHdpdGggJFxhbHBoYV4yIFx0aW1lcyBcYmV0YV8xJA0KDQpHZW5lcmFsaXplczogdGhlIGVmZmVjdCBvZiAkWF90JCBhbnkgYXJiaXRyYXJ5IGxlYWRzIGludG8gdGhlIGZ1dHVyZSBpcyBnb2luZyB0byBiZSAkXGFscGhhXmQgXHRpbWVzIFxiZXRhXzEkIHdoZXJlICRkJCBpcyBob3dldmVyIG1hbnkgbGVhZHMgd2Ugd2FudC4gDQoNCk5vdGUgdGhhdCB0aGUgZWZmZWN0IG9mICRYX3QkIGRlY2F5cyBiZWNhdXNlIG9mIHRoZSByZXF1aXJlbWVudCB0aGF0ICRcdmVydCBcYWxwaGEgXHZlcnQgPCAxJCAtIG90aGVyd2lzZSB0aGUgZWZmZWN0IGRvZXMgbm90IGRlY2F5IGF0IGFsbCAoJD0gMSQpIG9yIGluY3JlYXNlcyBpbiB0aW1lICgkPjEkKS4NCg0KIyMjIFNlcmlhbCBjb3JyZWxhdGlvbiBpbiBlcnJvciB0ZXJtDQpIYXZlbid0IG1hZGUgdG9vIG11Y2ggb2YgdGhpcyB1bnRpbCBub3cuDQoNCkluIGdlbmVyYWwsIHNlcmlhbCBjb3JyZWxhdGlvbiBpbiB0aGUgZXJyb3IgaXMgbm90IGEgYmlnIGlzc3VlIChubyBiaWFzIC8gaW5jb25zaXN0ZW5jeSkuDQoNCldlIGRvIGdldCBiYWQgU0UvdC1zdGF0cyB1bmRlciBzZXJpYWwgY29ycmVsYXRpb24uDQoNClR3byBhcHByb2FjaGVzOg0KDQoxLiBKdXN0IHVzZSBPTFMgYW5kIGNsZWFuIHVwIHRoZSBTRXMgdG8gYmUgcm9idXN0IHRvIHNlcmlhbCBjb3JyZWxhdGlvbiAoSEFDIFNFcywgUENTRXMpDQoNCjIuIFRyeSB0byBiZXR0ZXIgbW9kZWwgdGhlIGR5bmFtaWNzIHRvIGVsaW1pbmF0ZSBzZXJpYWwgY29ycmVsYXRpb24gLSBmb3IgZXhhbXBsZSB3aXRoIGRlZXBlciBsYWdzIG9mICRZJA0KDQpCdXQsIHdpdGggYW4gTERWLCBzZXJpYWwgY29ycmVsYXRpb24gaW4gdGhlIGVycm9yIGNyZWF0ZXMgYmlhcy4gIChAYWNoZW4yMDAwbGFnZ2VkLCBAa2VlbGUyMDA2ZHluYW1pYykNCg0KTmVlZCB0byBiZSBjYXJlZnVsIHRvIGVuc3VyZSBubyBzZXJpYWwgY29ycmVsYXRpb24gaW4gZXJyb3IgdGVybSBvZiB0aGUgbW9kZWwuDQoNCmBgYHtyfQ0KcGJndGVzdChkX2xtaWxleH5sYWdfbG1pbGV4K2RfcG9seWFyY2h5LCBkYXRhPWZkLCBtb2RlbD0icG9vbGluZyIsIG9yZGVyPTEpDQoNCmxkdjwtcGxtKGRfbG1pbGV4fmxhZ19sbWlsZXgrZF9wb2x5YXJjaHksIGRhdGE9ZmQsIG1vZGVsPSJwb29saW5nIikNCnJlc19kZiA8LSBkYXRhLmZyYW1lKHJlc2lkdWFsID0gcmVzaWR1YWxzKGxkdiksIGF0dHIocmVzaWR1YWxzKGxkdiksICJpbmRleCIpKQ0KDQpyZXNfZGY8LSByZXNfZGYgJT4lDQogIGxlZnRfam9pbihmZCwgYnk9YygiY2NvZGUiLCAieWVhciIpKQ0KDQpyZXNfZGYkbGFnX3JlcyA8LSBsYWcocmVzX2RmJHJlc2lkdWFsKQ0KDQpyZXNfZGY8LXBsbTo6cGRhdGEuZnJhbWUocmVzX2RmLCBpbmRleD1jKCJjY29kZSIsICJ5ZWFyIikpDQoNCndvb2xkcmlkZ2UgPC0gcGxtKHJlc2lkdWFsfmxhZ19yZXMsIG1vZGVsPSJwb29saW5nIiwgZGF0YT1yZXNfZGYpDQoNCndvb2xkcmlkZ2Vfc3RhdCA8LSAoY29lZih3b29sZHJpZGdlKVsyXSsuNSkgLyAoc3FydChkaWFnKHZjb3Yod29vbGRyaWRnZSkpWzJdKSkNCg0Kcm91bmQocGNoaXNxKHdvb2xkcmlkZ2Vfc3RhdCwgMSwgbG93ZXIudGFpbCA9IEYpLCBkaWdpdHM9MykNCg0KYGBgDQoNCk1peGVkIHJlc3VsdHMgLSBCcmV1c2NoIC0gR29kZnJleSB0ZXN0IGZhaWxzIHRvIHJlamVjdCwgV29vbGRyaWRnZSB0ZXN0IHJlamVjdHMuDQoNCiMgRHluYW1pYyBQYW5lbCBNb2RlbHMNCklmIHdlIGFzc3VtZSB1bml0IGVmZmVjdHMgdGhhdCBpbXBhY3QgJFkkIChhcyBpbiB0aGUgRkUvUkUgY2FzZSksIHRoZSBMRFYgbW9kZWwgaXMgYmlhc2VkLCBldmVuIGlmIHdlIGRvIG5vdCBhc3N1bWUgY29ycmVsYXRpb24gYmV0d2VlbiB0aGUgdW5pdCBlZmZlY3RzIGFuZCBpbmNsdWRlZCB2YXJpYWJsZXMgKEB3YXdybzIwMDJlc3RpbWF0aW5nIGlzIGFuIGFjY2Vzc2libGUgc3VtbWFyeSkuDQoNClRoaXMgaXMgYmVjYXVzZSB0aGUgc3RhdGljIGluZGl2aWR1YWwgZWZmZWN0cyBhcmUgcmVsZWdhdGVkIHRvIHRoZSBlcnJvciB0ZXJtLiAgVGhlIExEViBpcyBjb3JyZWxhdGVkIHdpdGggdGhvc2Ugc3RhdGljIHVuaXQgZWZmZWN0cywgc28gYnkgcHV0dGluZyBpdCBvbiB0aGUgUkhTIHdlJ3ZlIGNyZWF0ZWQgYmlhcy4NCg0KVW5saWtlIGluIHRoZSBzdGF0aWMgY2FzZSwgdGhlIEZFIGVzdGltYXRvciBpcyBhbHNvIGJpYXNlZC4gIFRoaXMgYmlhcyBpcyBzb21ldGltZXMgcmVmZXJyZWQgdG8gYXMgTmlja2VsbCBiaWFzIGFmdGVyIEBuaWNrZWxsMTk4MWJpYXNlcy4NCg0KSW50dWl0aW9uIGhlcmUgaXMgdGhhdCB0aGUgdHJhbnNmb3JtZWQgTERWIGFuZCBlcnJvciBhcmUgY29ycmVsYXRlZC4gVGhlIGdyb3VwIG1lYW4gb2YgdGhlIExEViBjb250YWlucyBhbGwgcmVhbGl6YXRpb25zIG9mICRZJCBtaW51cyB0aGUgZmluYWwgb2JzZXJ2YXRpb24gb2YgdGhlIHVuaXQuICBBbnkgJFlfdCQgaXMgY29ycmVsYXRlZCB3aXRoIHRoZSBhcHByb3ByaWF0ZSBlcnJvciAkZV90JCwgd2hpY2ggaXMgaW50cm9kdWNlZCBpbnRvIHRoZSBlcnJvciB0ZXJtIGJ5IHRoZSBncm91cCBkaWZmZXJlbmNlLg0KDQpCaWFzIGlzIGRlY3JlYXNpbmcgaW4gJFQkIG5vdCAkTiQgLSBzbyBpbiBzaG9ydCBwYW5lbHMgdGhlIGJpYXMgY2FuIGJlIHZlcnkgbGFyZ2UuDQoNCiMjIEFuZGVyc29uLUhzaWFvIEVzdGltYXRvcg0KDQoxLiBGaXJzdCBkaWZmZXJlbmNlIHRoZSByZWdyZXNzaW9uIGVxdWF0aW9uIHRvIHJlbW92ZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIExEViBhbmQgRkUgKG5vdGUgdGhpcyBpcyBub3QgZ3JvdXAgZGVtZWFuaW5nLCB3aGljaCB3b3VsZCBwcmV2ZW50IHZhbGlkIGluc3RydW1lbnRzLikNCg0KRmlyc3QgZGlmZmVyZW5jZWQgTERWIGlzIHN0aWxsIGNvcnJlbGF0ZWQgd2l0aCBmaXJzdCBkaWZmZXJlbmNlZCBlcnJvcg0KDQpCdXQsIHRoaXMgY2FuIGJlIGhhbmRsZWQgd2l0aCBzdGFuZGFyZCBJViBhcHByb2FjaGVzOiANCg0KMi4gIEluc3RydW1lbnQgZm9yICRcRGVsdGEgWV97dC0xfSQNCg0KRGVlcGVyIGxhZ3Mgb2YgJFkkIGFyZSB2YWxpZCBpbnN0cnVtZW50cywgc3BlY2lmaWNhbGx5ICRZX3t0LTJ9JC0gbm8gbmVlZCB0byBmaW5kIGFuIGluc3RydW1lbnQgKGFsdGhvdWdoIGlmIHlvdSBoYXZlIG9uZSB0aGF0IGFsc28gd29ya3MhKS4gIEhvd2V2ZXIsIHRoaXMgZGVwZW5kcyBvbiBubyBzZXJpYWwgY29ycmVsYXRpb24gaW4gdGhlIGVycm9ycy4NCg0KSW4gZ2VuZXJhbCwgdGhlIEFIIGVzdGltYXRvciBoYXMgYmVlbiBzdXBlcnNlZGVkIGJ5IEdNTSBlc3RpbWF0b3JzIHRoYXQgYnVpbGQgb24gdGhlIGRlZXBlciBsYWcgYXBwcm9hY2gsIHNvIGl0J3MgdHlwaWNhbGx5IG5vdCBhIG5hbWVkIHJvdXRpbmUuICBCdXQgd2UgY2FuIGVzdGltYXRlIGl0IGJ5IGhhbmQgdmlhIHN0YW5kYXJkIDJTTFMuDQoNCmBgYHtyfQ0KZmQkbDJfbG1pbGV4PWxhZyhmZCRkX2xtaWxleCwgMikNCmFoPC1pdnJlZyhkX2xtaWxleH5sYWdfbG1pbGV4K2RfcG9seWFyY2h5fCBsMl9sbWlsZXgrZF9wb2x5YXJjaHksIGRhdGE9ZmQgKQ0Kc3VtbWFyeShhaCkNCg0KDQpgYGANCg0KTm90ZSB0aGF0IHdlJ3ZlIG9ubHkgdXNlZCBpdnJlZywgd2hpY2ggaXMgc3RhbmRhcmQgMlNMUyBlc3RpbWF0aW9uIChub3QgMlNMUyB3aXRoIEZFKS4gIFRoaXMgaXMgYmVjYXVzZSB3ZSd2ZSBzd2VwdCBvdXQgdGhlIHVuaXQgZWZmZWN0cyB2aWEgZmlyc3QgZGlmZmVyZW5jaW5nIGFscmVhZHkuDQoNCg0KDQojIFJlZmVyZW5jZXMNCg==